Wie mache ich z.B. #define a #include...



  • Hallo,
    ich möchte ein Makro schreiben, dass

    DEFAULT(test, 123)
    

    in

    #ifndef test
    #define test 123
    #endif
    

    "präprozessort".

    #define DEFAULT(name, wert) \
    	#ifdef name \
    	#define name wert \
    	#endif
    

    erzeugt allerdings die Fehlermeldung:
    "'#' is not followed by a macro parameter"

    #define HASH #
    #define DEFAULT(name, wert) \
    	HASH ifdef name \
    	HASH define name wert \
    	HASH endif
    

    erzeugt die Fehlermeldung:
    "stray ‘#’ in program"



  • Laut http://stackoverflow.com/questions/7687634/is-there-a-way-to-escape-a-c-preprocessor-directive funktioniert

    #define HASH(x) x
    #define DEFAULT(name, wert) \
        HASH(#)ifdef name \
        HASH(#)define name wert \
        HASH(#)endif
    

    Dann müsstest du aber irgendwie den Präprozessor zweimal laufen lassen.


  • Mod

    C++kryptomatrix schrieb:

    #define HASH #
    #define DEFAULT(name, wert) \
    	HASH ifdef name \
    	HASH define name wert \
    	HASH endif
    

    erzeugt die Fehlermeldung:
    "stray ‘#’ in program"

    Dies ist schon fast, was du möchtest. Deswegen auch die Fehlermeldung. Dieses Makro erzeugt als Ausgabe

    # ifdef test # define test 123 # endif
    

    Und da dies dann dem C++-Compiler (und nicht dem Präprozessor, denn der ist nicht rekursiv!) vorgesetzt wird, erzeugt dieser eben die Fehlermeldung, denn

    # ifdef test # define test 123 # endif
    

    ist kein gültiges C++.

    Nun könnte man sich in die Frage vertiefen, wie man dem Präprozessor bei bringt, newlines in der Ausgabe zu generieren. So direkt ist das erst einmal nicht möglich, aber mag sein, dass irgendjemand einen dreckigen Trick kennt, mit dem man doch die gewünschte Ausgabe erreichen kann. Aber wie du hoffentlich merkst, hast du einen entscheidenden Fehler gemacht: Du hast nicht nach dem gefragt, was du erreichen willst, sondern danach wie du denkst, wie die Lösung aussehen würde (ein sogenanntes XY-Problem). Selbst wenn wir nach langer Diskussion irgendwie ein Makro finden, das tatsächlich den Text

    #ifndef test
    #define test 123
    #endif
    

    erzeugt, wäre dir wohl kaum geholfen, eben weil der Präprozessor nicht erneut auf den erzeugten Text angewandt wird. Daher: Was willst du wirklich erreichen?



  • Ich hab ein Programm in der ich eine Art "config datei" habe in der Einstellungen #define gemacht werden, also z.B.:
    #define BAUD_RATE 57600
    Mein Ziel ist es, dass wenn man diese Zeile weg lässt ein Standa.rt wert genommen wird.
    also:
    config.hpp:

    #define BAUD_RATE 57600
    

    default.hpp

    #ifndef BAUD_RATE
    #define BAUD_RATE 57600
    #endif
    

    Problem: Wenn man viele Einstellungen hat ist das sehr lang und übersichtlich. Deshalb wäre es gut wenn in der default.hpp stehen würde:
    DEFAULT(BAUD_RATE 57600)
    Das wäre deutlich kürzer.



  • Mein Tipp: Lager die Konfiguration lieber in eine eigene Datei aus, kannst ja ein bereits vorhandenes Dateiformat wie JSON oder XML nehmen, da gibts genug Parser dafür und lad die Konfiguration zur Laufzeit. Der User wird es sicher besser finden, wenn er die Baudrate ohne neu kompilieren ändern kann.

    Falls durch irgendwelche Umstände das nicht möglich ist, schreib ein kleines Programm, dass dir aus einer Liste eine Quellcode-Datei mit den entsprechenden Präprozessoranweisungen generieren kann. Die meisten IDEs und Build-Tools können vor dem kompilieren noch andere Programme aufrufen, da passt das ganze schön rein.

    Übrigens, Standard schreibt man mit D. Deshalb wird die Version mit T auch blockiert.



  • patrick246 schrieb:

    Mein Tipp: Lager die Konfiguration lieber in eine eigene Datei aus, kannst ja ein bereits vorhandenes Dateiformat wie JSON oder XML nehmen, da gibts genug Parser dafür und lad die Konfiguration zur Laufzeit. Der User wird es sicher besser finden, wenn er die Baudrate ohne neu kompilieren ändern kann.

    Falls durch irgendwelche Umstände das nicht möglich ist, schreib ein kleines Programm, dass dir aus einer Liste eine Quellcode-Datei mit den entsprechenden Präprozessoranweisungen generieren kann. Die meisten IDEs und Build-Tools können vor dem kompilieren noch andere Programme aufrufen, da passt das ganze schön rein.

    Das funktioniert leider beides nicht, da ich, wieso ist kompilziert, das Programm nur durch kopieren der Quellcode-Dateien von einem PC auf den anderen machen muss.
    Geht es irgendwie als Makro?



  • C++kryptomatrix schrieb:

    Das funktioniert leider beides nicht, da ich, wieso ist kompilziert, das Programm nur durch kopieren der Quellcode-Dateien von einem PC auf den anderen machen muss.

    Den Satz verstehe ich nicht.



  • Also. Das mit der externen Config-Datei funktioniert nicht, da alle einstellungen in der .exe drin sein müssen.
    Das mit dem "Prä-programm" funktioniert auch nicht, weil. Geht es auch irgendwie als makro?



  • C++kryptomatrix schrieb:

    Das mit dem "Prä-programm" funktioniert auch nicht, weil.

    Sorry, aber wenn du uns nicht sagst, warum das nicht funktioniert, dann können wir dir leider nicht helfen...



  • C++kryptomatrix schrieb:

    Also. Das mit der externen Config-Datei funktioniert nicht, da alle einstellungen in der .exe drin sein müssen.

    Also erstmal ist das ("nur eine .exe und sonst nix") eine Forderung die meist nur aus der Unverständnis der ganzen Probleme die man sich damit einhandelt entsteht. Der Kunde will es so weil das halt "praktisch wäre" und "ja eh kein Problem sein kann", und der Entwickler muss es ausbaden. Was oft zu nem signifikanten Mehraufwand führt. z.B. scheidet damit schonmal die Verwendung von allen Libraries/Komponenten aus die man nur in DLL Form bekommt, bzw. wird dadurch deutlich verkompliziert.

    Ansonsten...
    Du kannst auch Files als Resource mit in ein .exe File reincompilieren. Unter Windows musst du dazu nur nen passenden Eintrag im .rc File machen, den Rest erledigt der Resource-Compiler für dich. Unter Linux wird es vermutlich ein ähnliches Feature geben.

    Und natürlich kannst du die Datenstrukturen einfach so auslegen dass du z.B. sowas wie Default-Werte nicht doppelt und dreifach angeben musst.

    C++kryptomatrix schrieb:

    Das mit dem "Prä-programm" funktioniert auch nicht, weil. Geht es auch irgendwie als makro?

    Aha, weil.
    Dann mach es einfach trotzdem so. Weil.



  • C++kryptomatrix schrieb:

    Ich hab ein Programm in der ich eine Art "config datei" habe in der Einstellungen #define gemacht werden, also z.B.:
    #define BAUD_RATE 57600
    Mein Ziel ist es, dass wenn man diese Zeile weg lässt ein Standa.rt wert genommen wird.
    also:
    config.hpp:

    #define BAUD_RATE 57600
    

    default.hpp

    #ifndef BAUD_RATE
    #define BAUD_RATE 57600
    #endif
    

    Problem: Wenn man viele Einstellungen hat ist das sehr lang und übersichtlich. Deshalb wäre es gut wenn in der default.hpp stehen würde:
    DEFAULT(BAUD_RATE 57600)
    Das wäre deutlich kürzer.

    #ifdef RELEASE
    #include "config.hpp"
    #else
    #include "default.hpp"
    #endif
    

    Edit: OK, jetzt verstehe ich deinen Ansatz. Wie die anderen schon geschrieben haben: Tu die Config-Parameter in eine eigene Datei und lies sie zur Laufzeit ein. Oder eben zwei verschiedene Header-Dateien.



  • C++kryptomatrix schrieb:

    Das mit dem "Prä-programm" funktioniert auch nicht, weil. Geht es auch irgendwie als makro?

    Eigentlich sollte es gehen, weil.

    Z.B. mit einem eigenen File für die defaults(hier 'default_settings.txt')

    ; the following file contains the default settings
    ; for several c-macros
    ; users are encouraged to change these defaults
    ; where necessary in their config.h file
    
    BAUDRATE 57600
    PORTNAME "dev/ttyS0"
    ANSWER   42
    

    und einem awk-script o.ä., dass Du in den buildprocess einbaust...meinetwegen auch händisch aufrufst

    furblewurble@sinsemilla /tmp $ awk 'BEGIN {print "// This file is automagically created from default_settings.txt\n// Do not try to edit its content.\n\n"}$1!~/(^\s*;)|(^$)/{print "#ifndef " $1"\n#define " $1" " $2"\n#endif\n"}' <default_settings.txt > default.h
    

    (bin kein awk-Experte...aber die Idee kommt rüber)

    Das ergibt dann in dem Beispiel die schöne default.h:

    // This file is automagically created from default_settings.txt
    // Do not try to edit its content.
    
    #ifndef BAUDRATE
    #define BAUDRATE 57600
    #endif
    
    #ifndef PORTNAME
    #define PORTNAME "dev/ttyS0"
    #endif
    
    #ifndef ANSWER
    #define ANSWER 42
    #endif
    


  • Also...

    hustbaer schrieb:

    C++kryptomatrix schrieb:

    Also. Das mit der externen Config-Datei funktioniert nicht, da alle einstellungen in der .exe drin sein müssen.

    Also erstmal ist das ("nur eine .exe und sonst nix") eine Forderung die meist nur aus der Unverständnis der ganzen Probleme die man sich damit einhandelt entsteht. Der Kunde will es so weil das halt "praktisch wäre" und "ja eh kein Problem sein kann", und der Entwickler muss es ausbaden. Was oft zu nem signifikanten Mehraufwand führt. z.B. scheidet damit schonmal die Verwendung von allen Libraries/Komponenten aus die man nur in DLL Form bekommt, bzw. wird dadurch deutlich verkompliziert.

    Es gibt keinen "Kunden", das Programm steuert einen Roboter auf einem Roboter Wettbewerb. Da ich dass Programm des oft von einem PC/Chip auf den anderen übertragen muss, will ich nicht jedes mal config.txt dateien oder "prä-programme" mitschleppen.



  • rofl
    ok
    dann mach mal wie du meinst


Anmelden zum Antworten