Funktionszeiger definition <-> (extern)-Deklaration



  • extern void(*foo)(); // extern-Deklaration des Funktioneszeigers foo
    void(*foo)(); // zugehörige Deklaration

    extern "C" void(*foo)(); //extern-Deklaration des Funktionszeigers foo der auf eine Funktion mit C-Bindung zeigt
    //? zugehörige Deklaration 😕 😕



  • Hallo,
    meines Wissens nach geht das nur mit einem typedef. Und dann auch nicht gerade intuitiv:

    extern "C" void foo();
    extern "C" typedef void(*func)();
    int main()
    {
    func p = &foo;
    
    }
    

    Oder habe ich jetzt deine Frage missverstanden? Kann es sein, dass du statt Deklaration Definition meintest?

    PS: Eine Linkage-specification darf nur im Namespace-Scope auftauchen.

    PPS: Ich glaube du meintest eher das, oder?

    extern "C" typedef void(*cFunc)();
    extern cFunc func;    // extern-Deklaration
    cFunc func;           // zugehörige *Definition*
    


  • Oder habe ich jetzt deine Frage missverstanden?

    ich glaube ja
    bei

    extern "C" typedef void(*func)();

    krieg ich auch nen Fehler: "Zu viele Speicherklassen in der Deklaration"

    Möchte die Funktionen von ner DLL möglichs elegant (d.h. dass der Client viel tun muss) dynamisch importieren.

    Hab mir das so gedacht:
    - Mit 'extern' deklarier ich eine Variable ohne sie zu definieren (extern int i;)
    -> ich möchte mit extern die Funktionszeigervariable deklariern.
    - Gehe davon aus, dass das "C" da keinen unterschied macht
    extern "C" void(*foo)();
    - in einem Cpp-File muss ich jetzt meine Funktionszeigervariable noch definieren -> 😕
    - Dann müssen die Funktionen nur noch reingeladen und den Zeigern zugewiesen werden

    //header----------
    
    //definition des Funktionstyps
    typedef void(*foo_type)();       //geht, aber kann das richtig sein?
    //typedef extern "C" foo_type;   //geht nicht
    
    //Bekanntgabe dass es den Funktionszeiger gibt (Deklaration)
    //extern extern "C" foo_type foo; //mir wärs so am einleutendsden. Geht aber nicht
    extern "C" foo_type foo;          //deklariert? oder doch definiert???
    
    //cpp-------------
    
    //Definition der deklarierten Funktionszeigervariable
    foo_type foo;                    //so? Aber wo bleibt das "C"
    //extern "C" foo;                //so? Aber das ist doch wieder nur eine Deklaration
    
    void loadFooDLL()
    {
      HANDLE module( LoadLibrary("meine.dll"));
      foo = foo_type( GetProcAddress(module,"_foo"));  //initialisieren der Funktionezeigervariable
    }
    

    Ohne das "C" wär mir alles klar. Aber mit dem "C"? Entweder extern "C" ist eine extern-Deklaration, wie definier ich dann meine Funktionszeigervariable, oder extern "C" ist keine extern-Deklaration im eigentlichen Sinne, aber wie mach ich dann eine solche???

    [edit]
    Dein Nachtrag: genau das hab ich gemeint 👍
    Nur leider mag das wie gesagt mein C++Builder nicht 👎
    Der Comeau compilierts aber 🤡
    und jetzt 😞



  • So nimmt ers:

    //header----------
    
    extern "C"{
      typedef void(*foo_type)();
      extern  foo_type foo;
    }
    
    //cpp-------------
    
    extern "C"{
      foo_type foo;
    }
    

    Müsste dasselbe sein, oder?

    [Edit]
    Ah, jetzt kapier ich, warum Du mich nicht kapiert hast 😉 Hab oben vor lauter nachdenken immer nur *Deklaration* geschrieben!



  • Hallo,
    mein nachträglich hinzugefügtes Beispiel macht genau das, was du willst.
    Also
    a) Eine Variable vom Typ "Zeiger auf Funktion mit C-Linkage" deklarieren, aber nicht definieren:

    // Header.h
    extern "C" typedef void (*PointerToCFunc)();
    extern PointerToCFunc myFuncPointer;
    

    b) In einer cpp-Datei den zuvor deklarierten Zeiger definieren:

    #include "header.h"
    PointerToCFunc myFuncPointer;
    

    So ist das Standard-C++. Wenn dein Compiler das nicht schluckt, dann ist das ein Fehler. Was du dagegen machen kannst, weiß ich leider auch nicht.

    Allerdings unterscheiden viele Compiler typmäßig nicht zwischen einer normalen C++ Funktion und einer Funktion mit C-Linkage. D.h. du kannst da sowas machen:

    extern void (*myFuncPointer)();	// Deklaration in der h
    
    void (*myFuncPointer)();		// Definition in der cpp-Datei
    
    extern "C" void cFunc();
    void cppFunc();
    int main() 
    {
    	myFuncPointer = cFunc;
    	myFuncPointer = cppFunc;
    }
    


  • Ok. Wir haben ein Synchronisationsproblem 😃



  • Müsste dasselbe sein, oder?

    Yep. Wenn der BCC das mitmacht, kannst du imo sogar den extern "C"-Block in der cpp-Datei weglassen.



  • muchas gracias! 👍 🙂



  • Ich versteh jetzt nicht ganz was du willst, könnte es nicht einfac sein, dass du dynamisch eine gamz gewöhnlich Funktion linken willst? Fals ja dann geht das so für Win32:
    Hier die definition (gehört in die dll). Das __stdcall haut die Namesverschlüsselung weg:

    extern "C" void __stdcall __declspec(dllexport) foo();
    

    Hier nun die Definition (gehört auch in die DLL):

    extern "C" void __stdcall __declspec(dllexport) foo(){
      //...
    }
    

    Und um nun at runtime, also dynamisch, zu linken tuts du das hier:

    HINSTANCE dll=LoadLibrary("dll name");
    void (__stdcall *foo)()=(void (__stdcall *)())GetProcAddress(dll,"foo");
    (*foo)();//Aufruf
    FreeLibrary(dll);
    

    Kleiner Tip wenn du nicht weist wie dein Compiler ein Funktions Pointer gerne declarirt hat dann weis einfach den pointer (also in diesem Fall foo) einem char* oder irgend einem garatiert incompatible Typ zu. Nun wird der Kompiler meckern:

    Cannot convert 'void (__stdcall *)()' to 'char *'

    (oder so ähnlich) und dann hast du den Typ. Error sind auch manchmal was schönes. 😃


Anmelden zum Antworten