qualified-id in declaration before '(' token
-
geht leider so nicht: (...)
Ja, das ist halt jetzt ein anderer, zusätzlicher Fehler.
es funktioniert (...)
[&]
ist Overkill,[this]
wie ich geschrieben habe sollte reichen.
-
Wie so oft ist ein Problem nicht so trivial, wie es zu Beginn scheint. Das obige Funktioniert, hat aber den Nachteil, dass der String immer in die erste Zeile der Datei geschrieben wird. Meine Datei hat in etwa folgenden Inhalt:
rotation=1
timeout=10
LANG=de_DE.UTF-8Ich muss es daher noch realisieren, dass der String in die Zeile geschrieben wird, in der der alte String stand. Sollte der String noch nicht vorhandene ein, soll er hinten angehängt werden. Ich habe den Hinweis bekommen, dass das mit folgendem Skript geht:
https://github.com/XCSoar/XCSoar/blob/f829b8f394d2eb21c276d17f38b134bc3f9e7466/src/Profile/File.cppIch habe mir andere Dateien angeschaut, in denen Profile::LoadFile vorkommt, verstehe aber die Funktionsweise noch nicht. Nach meinem Verständnis muss ich ja den zu suchenden String und den Pfad angeben. Daher habe ich mir was in der Art gedacht:
Profile::LoadFile("LANG*", "/boot/config.uEnv");Nach dem ich mir die Beispiel angeschaut habe bin ich mir ziemlich sicher, das it Blödsinn. Vielleicht kann mir jemand helfen die Funktion besser zu Verstehen.
Danke!!
-
Man lädt einmalig die Datei mit
LoadFile
und übergibt eine leereProfileMap
.
Anschließend ändert man die Werte in derProfileMap
und speichert dann mitSaveFile
wieder die gesamte Datei ab (man kann in einer Textdatei nicht direkt einzelne Zeilen ersetzen).
-
@hustbaer Danke, ändere ich!!
-
@Th69 Danke!! Das hilft für das Verständnis sehr weiter!!!
-
Ich versuche mich gerade in das Thema ProfileMap einzuarbeiten. Ich versuche mal kleinschrittige Fragen zu stellen, um es besser verstehen zu können.
Die Funktion LoadConfig müsste also ein map mit dem Namen configuration anlegen und jede Zeile der Datei /boot/config.uEnv auslesen. Dann wird z.B. dem key1 rotation und als Wert 1, dem key3 LANG und als Wert de_DE.UTF-8, etc zugewiesen. Habe ich das bis hierher korrekt verstanden?
static void LoadConfig() { Profile::Clear(); Profile::LoadFile(configuration, "/boot/config.uEnv"); }
Aufgerufen wird die Funktion mit:
LoadConfig();
-
Ja, du mußt eine Variable dafür anlegen:
ProfileMap configuration;
und dann kannst du (entsprechend Map.hpp) eine der
Set
-Funktionen dafür aufrufen, z.B.configuration.Set("rotation", 1);
-
Ich hoffe, ich hab es korrekt verstanden. Dann müsste die Funktion so aussehen:
static void LoadConfig(&keyvalue, &value) { ProfileMap configuration; Profile::Clear(); Profile::LoadFile(configuration, "/boot/config.uEnv"); configuration.Set(keyvalue, value); }
Und die Funktion müsste dann so aufgerufen werden, oder?
LoadConfig("rotation", 1);
-
Fast - du mußt noch die richtigen Typen bei den Funktionsparametern angeben (C++ ist typsicher).
Und&
ist nur bei Referenzparametern anzugeben.Und ich würde die Funktion ' ChangeConfig' nennen und noch den 'Profile::SaveFile(...)'-Aufruf hinzufügen (sonst macht die Funktion bisher nichts wirklich sinnvolles).
PS: Wenn du verschiedene Typen für
value
benötigst (und nicht nurint
), dann brauchst du hier schon fortgeschrittenere C++-Funktionalität:template
.
-
Vielen Dank für deine geduldige Erklärung!!
Ich habe die Funktion soweit angepasst:
static void ChangeConfig(const sting keyvalue, const sting value) { ProfileMap configuration; Profile::Clear(); Profile::ChangeConfig(configuration, "/boot/config.uEnv"); configuration.Set(keyvalue, value); Profile::SaveFile(configuration, "/boot/config.uEnv"); }
Der Aufruf erfolgt mit:
ChangeConfig("rotation", 1);
Der Teil müsste so nun funktionieren, oder?
Tatsächlich wird es auch einen Aufruf in der Art geben müssen:
ChangeConfig("LANG", "de_DE.UTF-8");
Das heißt, wenn ich dich richtig verstehe, dass das so noch nicht geht?
-
Kompilieren bringt noch Fehler:
| src/OV/OpenVarioMenu.cpp:98:16: error: aggregate 'ProfileMap configuration' has incomplete type and cannot be defined | 98 | ProfileMap configuration; | | ^~~~~~~~~~~~~ | src/OV/OpenVarioMenu.cpp:99:14: error: 'Clear' is not a member of 'Profile' | 99 | Profile::Clear(); | | ^~~~~ | src/OV/OpenVarioMenu.cpp:100:14: error: 'ChangeConfig' is not a member of 'Profile'; did you mean 'ChangeConfig'? | 100 | Profile::ChangeConfig(configuration, "/boot/config.uEnv"); | | ^~~~~~~~~~~~ | src/OV/OpenVarioMenu.cpp:96:13: note: 'ChangeConfig' declared here | 96 | static void ChangeConfig(const string keyvalue, const string value) | | ^~~~~~~~~~~~ | make: *** [build/compile.mk:107: output/UNIX/opt/src/OV/OpenVarioMenu.o] Error 1
-
Sorry, aber so wird das nichts - du mußt schon die Grundlagen (Syntax und Semantik) von C++ verstehen.
Am besten (wenn du englisch kannst) mittels LearnCpp.
Es gibt auch noch (für den Einstieg) Wiki: C++ Programmierung.
Sonst s.a. noch Linkliste.Ich gebe dir jetzt (einmalig) mal den Code:
#include "Map.hpp" // für ProfileMap static void ChangeConfig(const string &keyvalue, int value) { const char * const ConfigPath = "/boot/config.uEnv"; // um nur eine Codestelle dafür zu haben ProfileMap configuration; // Profile::Clear(); // <- diese Funktion gibt es wohl nicht bei XCSoar Profile::LoadFile(configuration, ConfigPath); // Funktionsname wieder zurück geändert configuration.Set(keyvalue, value); Profile::SaveFile(configuration, ConfigPath); }
Für andere Aufrufe (z.B.
string
) bräuchtest du, wie schon geschrieben, ein Template:template<typename T> static void ChangeConfig(const string &keyvalue, T value) { // der Rest bleibt gleich }
-
Danke!! Ich schaue mir deine Empfehlungen an. So ganz allmählich blicke ich es aber schon. Allerdings führt deine Code noch zu Fehlern:
| src/OV/OpenVarioMenu.cpp: In function 'void ChangeConfigInt(const string&, int)': | src/OV/OpenVarioMenu.cpp:102:38: error: could not convert 'ConfigPath' from 'const char* const' to 'Path' | 102 | Profile::LoadFile(configuration, ConfigPath); | | ^~~~~~~~~~ | | | | | const char* const | src/OV/OpenVarioMenu.cpp:103:22: error: no matching function for call to 'ProfileMap::Set(const string&, int&)' | 103 | configuration.Set(keyvalue, value); | | ~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~ | In file included from src/OV/OpenVarioMenu.cpp:42:
-
Ich habe mir die genaue API nicht angeschaut, sondern mich nur an deinem Code (+ den Fehlermeldungen) orientiert.
Du mußt anscheinend ein Objekt der Klasse Path erzeugen und übergeben:const Path ConfigPath("/boot/config.uEnv"); // evtl. für Unicode: L"/boot/config.uEnv"
Und statt
string
muß wohl direktconst char *
als Typ fürkeyvalue
verwendet werden (oder aber du benutzt beim Aufrufconfiguration.Set(keyvalue.c_str(), value)
.
-
Es läuft noch nicht ganz. Ich habe heute viel gelesen, um das Problem möglichst selbst zu finden, und denke, ich bin grundsätzlich auf der richtigen Spur. Folgender Fehler kommt noch:
| LINK output/UNIX/bin/OpenVarioMenu | src/OV/OpenVarioMenu.cpp:176: error: undefined reference to 'Profile::LoadFile(ProfileMap&, Path)' | src/OV/OpenVarioMenu.cpp:177: error: undefined reference to 'ProfileMap::Set(char const*, int)' | src/OV/OpenVarioMenu.cpp:178: error: undefined reference to 'Profile::SaveFile(ProfileMap const&, Path)' | collect2: error: ld returned 1 exit status
Das Problem ist wohl, das Profile nicht public ist. Soweit ich das recherchieren konnte, muss die Funktion ChangeConfigInt in Zeile 171 und folgende eingebunden werden. Damit sollte sie eigentlich public sein. Ich nehme aber an, dass da noch eine Kleinigkeit fehlt.
Hier noch mal der Link zum Skript, damit es besser nachvollziehbar ist: https://github.com/freevariode/XCSoar/blob/master/src/OV/OpenVarioMenu.cpp
-
Mit public/protected/private hat das nichts zu tun.
Das Problem ist dass die drei Funktionen einfach nirgends definiert sind.
-
Siehst du beim Kompilieren eine Liste der Dateien?
Dabei sollten dann sowohl src/Profile/File.cpp als auch src/Profile/Map.cpp auftauchen (eigenartigerweise ist dort aber nurProfileMap::Set(const char *key, const char *value)
definiert und nicht die anderenSet
-Überladungen, auch nicht in der Headerdatei ProfileMap.hpp).Nach Suche habe ich aber dann herausgefunden, daß die
ProfileMap
-Funktionen über diverse andere Source-Dateien (u.a. NumericValue.cpp) verteilt sind (very strange).
Es sollten also alle Source-Dateien im Profile-Ordner mitkompiliert werden, so daß es keine Linkerfehler mehr gibt.
-
also in der Liste der Dateien beim Kompilieren kommen unter Anderem diese Dateien vor:
| CXX output/UNIX/opt/src/Profile/Profile.o | CXX output/UNIX/opt/src/Profile/File.o | CXX output/UNIX/opt/src/Profile/Map.o
wie in dieser Datei (https://github.com/XCSoar/XCSoar/blob/master/src/Input/InputEventsSettings.cpp) habe ich auch versuchsweise folgendes eingetragen:
#include "Profile/Profile.hpp" #include "Profile/ProfileKeys.hpp" #include "Profile/Settings.hpp" #include "Profile/Current.hpp"
Aber das verändert nichts. Ich verstehe nicht, was in dieser Datei anders gemacht wird als in meiner.
-
Ganz zum Schluß sollte es einen (wahrscheinlich sehr langen) Linkeraufruf geben, in welcher dann alle Objektfiles (
.o
) übergeben werden müssen - tauchen dort dann u.a.File.o
,Map.o
und auchNumericValue.o
auf?Du solltest zumindestens den Compile- und Linkprozess verstehen, s. z.B. (in englisch) Introduction to the compiler, linker and libraries.
-
Du meinst diesen Bereich?
| LINK output/UNIX/bin/xcsoar | rm output/data/icons/winpilot_reachable_160_alpha.png output/data/icons/map_teammate_rgb.png output/data/icons/map_taskturnpoint_alpha.png output/data/icons/winpilot_marginal_160_rgb.png output/data/icons/gps_lowsignal_160_rgb.png output/data/icons/map_intersection_160_rgb.png output/data/icons/map_ndb_160_rgb.png output/data/icons/wrench_160_rgb.png output/data/icons/map_tunnel_160_rgb.png output/data/icons/map_target_rgb.png output/data/icons/alt_marginal_airport_160_rgb.png output/data/icons/map_small_160_alpha.png output/data/icons/map_pgtakeoff_alpha.png output/data/icons/map_reporting_point_160_alpha.png output/data/icons/map_turnpoint_alpha.png output/data/icons/gps_disconnected_rgb.png output/data/icons/map_mountain_top_rgb.png output/data/icons/map_intersection_160_alpha.png output/data/icons/gps_lowsignal_rgb.png output/data/icons/map_thermal_source_160_alpha.png output/data/icons/alt_marginal_field_160_rgb.png output/data/icons/flarm_alarm_alpha.png output/data/icons/map_town_alpha.png output/data/ ... gaaaaaaaaanz viele Zeilen ... | NOTE: make -j 4 HOSTCC=ccache gcc HOSTCXX=ccache g++ AR=arm- ovlinux-linux-gnueabi-gcc-ar RANLIB=arm-ovlinux-linux-gnueabi-gcc-ranlib CXX=ccache arm-ovlinux-linux-gnueabi-g++ -mthumb -mfpu=neon -mfloat- abi=hard -mcpu=cortex-a7 -fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wformat -Wformat-security -Werror=format-security -- sysroot=/workdir/tmp/work/cortexa7t2hf-neon-ovlinux-linux-gnueabi/xcsoar- testing/git-r13/recipe-sysroot CC=ccache arm-ovlinux-linux-gnueabi-gcc - mthumb -mfpu=neon -mfloat-abi=hard -mcpu=cortex-a7 -fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wformat -Wformat-security -Werror=format- security --sysroot=/workdir/tmp/work/cortexa7t2hf-neon-ovlinux-linux- gnueabi/xcsoar-testing/git-r13/recipe-sysroot AS=arm-ovlinux-linux-gnueabi-as LD=arm-ovlinux-linux-gnueabi-ld --sysroot=/workdir/tmp/work/cortexa7t2hf- neon-ovlinux-linux-gnueabi/xcsoar-testing/git-r13/recipe-sysroot STRIP=arm- ovlinux-linux-gnueabi-strip CCACHE= DEBUG=n DEBUG_GLIBCXX=n ENABLE_MESA_KMS=y GLES2=y GEOTIFF=n output/UNIX/bin/OpenVarioMenu | CXX output/UNIX/opt/src/Dialogs/ProcessDialog.o | CXX output/UNIX/opt/test/src/Fonts.o | CXX output/UNIX/opt/test/src/FakeLanguage.o | CXX output/UNIX/opt/test/src/FakeLogFile.o | CXX output/UNIX/opt/src/Kobo/FakeSymbols.o | CXX output/UNIX/opt/src/OV/OpenVarioMenu.o | LINK output/UNIX/bin/OpenVarioMenu
Da kommt Map.o, File.o etc nicht vor