Programm kompatibel halten mit defines



  • HumeSikkins schrieb:

    Ja. Solcher Code ist schwer zu lesen, schwer zu warten und schwerer zu testen. Zumindest auf Funktionsebene solltest du das besser sein lassen. Auf globaler Ebene hingegen ist es in Maßen ok.

    findest du sowas schlecht und unleserlich ?

    // zentraler header
    #if defined(_WIN32)
    	#define PLUGIN_HANDLE			HINSTANCE
    	#define PLUGIN_LOAD(a)			LoadLibrary(a)
    	#define PLUGIN_GETADR(a, b)		GetProcAddress(a, b)
    	#define PLUGIN_UNLOAD(a)		FreeLibrary(a)
            // ...
    #elif defined(LINUX)
    	#define PLUGIN_HANDLE			void *;
    	#define PLUGIN_LOAD(a)			dlopen(a, RTLD_LAZY)
    	#define PLUGIN_GETADR(a, b)		dlsym(a, b)
    	#define PLUGIN_UNLOAD(a)		dlclose(a)
            // ...
    #endif
    
    // verwendung
    PLUGIN_HANDLE m_Handle = (PLUGIN_HANDLE)PLUGIN_LOAD(szName);
    // usw usw
    

    ich finde das ganz gut. ist das nicht ehr eine stil frage ? oder spricht irgendwas gravierendes dagegen ?



  • oder spricht irgendwas gravierendes dagegen ?

    die existenz von konstanten,enums, typedefs und templates?



  • Na ja, erstens sollte man #defines für so etwas ja vermeiden und zweitens wer benennt die dann "WIN32" oder "LINUX"?



  • otze schrieb:

    die existenz von konstanten,enums, typedefs und templates?

    klar könnte ich diesen auch so lösen aber es ging mir mal um richtig oder krautfalsch oder stilfrage. denn ich sehe keinen fehler dieses so zu machen wegen vier funktionen. wenn es allerdings aufwendiger wird (erstellung eines fenster's als beispiel) dann halte ich mich natürlich an deine variante.

    Definer schrieb:

    Na ja, erstens sollte man #defines für so etwas ja vermeiden und

    aha, sehr gute begründung. sollte in die faq.

    Definer schrieb:

    zweitens wer benennt die dann "WIN32" oder "LINUX"?

    windows kompilier zum bespiel siehe http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/_predir_predefined_macros.asp



  • wieso man keine defines benutzt:
    1. ein define macht kein halt vor scopegrenzen
    2. da es sich nicht an scopegrenzen hält, kann es dir im flal eines schlechten namenssystems ganz schnell ein paar hard to find bugs bescheeren, bei const/typedef/enum etc ist dieses problem nicht so extrem.

    3. zu deinem problem würden traits wunderbar passen



  • @miller_m
    Furchtbar! Schrecklichstes C Mittelalter! 🙂

    Für so etwas schreibt man sich einen schönen Wrapper und macht das dann so wie Hume es gezeigt hat. Ansonsten kann man Platformabhängige Sachen auch leicht mit Policies kapseln und dann folgendes machen

    //posix/policy.hpp
    
    struct posix_policy {
      //... POSIX kompatibler Code
    };
    
    //win32/policy.hpp
    
    struct win32_policy {
      //... WIN32 kompatibler Code
    };
    
    //policy.hpp
    
    #ifdef POSIX
    #include "posix/policy.hpp"
    typedef posix_policy policy;
    #elif WIN32
    #include "win32/policy.hpp"
    typedef win32_policy policy;
    #else
    #error "Keine Policy für die Platform vorhanden"
    #endif
    
    //klasse.hpp
    
    #include "policy.hpp"
    
    template<class Policy>
    class klasse_policy {
      //...
    };
    
    typedef klasse_policy<policy> klasse;
    


  • king, würde in dem fall der ausdruck traits nicht weitaus treffender sein, als policy?

    oder verwechsel ich da wiedermal was?



  • [quote="miller_m"]

    otze schrieb:

    Definer schrieb:

    Na ja, erstens sollte man #defines für so etwas ja vermeiden und

    aha, sehr gute begründung. sollte in die faq.

    Otze hat es zwar schon beantwortet aber ansonsten kannst du noch effective C++ lesen, wobei ich eher glaube das du weißt "warum"



  • otze schrieb:

    king, würde in dem fall der ausdruck traits nicht weitaus treffender sein, als policy?

    oder verwechsel ich da wiedermal was?

    Nein, Policy ist schon richtig. Traits beschreiben ja eher eine Policy für einen Typ 🙂



  • miller_m schrieb:

    findest du sowas schlecht und unleserlich ?

    // zentraler header
    #if defined(_WIN32)
    	#define PLUGIN_HANDLE			HINSTANCE
    	#define PLUGIN_LOAD(a)			LoadLibrary(a)
    	#define PLUGIN_GETADR(a, b)		GetProcAddress(a, b)
    	#define PLUGIN_UNLOAD(a)		FreeLibrary(a)
            // ...
    #elif defined(LINUX)
    	#define PLUGIN_HANDLE			void *;
    	#define PLUGIN_LOAD(a)			dlopen(a, RTLD_LAZY)
    	#define PLUGIN_GETADR(a, b)		dlsym(a, b)
    	#define PLUGIN_UNLOAD(a)		dlclose(a)
            // ...
    #endif
    
    // verwendung
    PLUGIN_HANDLE m_Handle = (PLUGIN_HANDLE)PLUGIN_LOAD(szName);
    // usw usw
    

    ich finde das ganz gut. ist das nicht ehr eine stil frage ? oder spricht irgendwas gravierendes dagegen ?

    http://www.artima.com/cppsource/reducepnpP.html



  • nagut jetzt habt ihr mich überzeugt. 😃
    werd mir heut abend mal policy's anschauem.



  • Die Namenskollisionen sind nur ein Problem, man kann bei sowas natürlich auch auftretende Fehler nicht behandeln, weil dlopen und LoadModule verschiedene Fehlercodes haben, usw.

    Nur kommen mir Policys für das Plugin-Beispiel auch ein *klein* wenig übertrieben vor. Wofür templates ins Boot holen, für Sachen, die eh nur von Kompilierung zu Kompilierung unterschiedlich sein können? Innerhalb eines Projekts wird ja niemand Foo<LinuxPolicy> und Foo<WindowsPolicy> mischen wollen, was mit templates natürlich ginge.

    namespace Plugin
    {
        #ifdef WIN32
        typedef HMOBULE Handle;
        #else
        typedef void* Handle;
        #endif
    
        Handle load(const std::string&) ...
    }
    

    Oder noch viel besser, eine Plugin-Klasse, deren private-Teil entweder per #ifdef ausgewählt oder durch das pimpl-Idiom einfach komplett nach draußen geschoben wird. Da muss man fürs Benutzen von Plugins nicht einmal implizit windows.h inkludieren und spart sich evtl. ne Menge Compilezeit.

    On-Topic? Was ist das?


Anmelden zum Antworten