GetProcAddress returnt NULL



  • Hoi,

    //DLLCLASS DLL.H
    class test1
    {
    public:
    void funcoftest1();
    
    };
    
    //DLLCLASS DLL.CPP
    
    void test1::funcoftest1()
    {
    MessageBox(NULL,L"Hi",NULL,NULL,NULL);
    }
    
    //main.cpp
    typedef void (*funcoftest1_Type)();
    funcoftest1_Type f1;
    HMODULE h1
    int main()
    {
    h1 = LoadLibrary("MyDLL");
    if(h1 == NULL)
    {
    MessageBox(NULL,L"Failed to Load the DLL",NULL,NULL,NULL);
    }
    f1 = (funcoftest1_Type)GetProcAddress(h1,"funcoftest1");
    if(f1 == NULL)
    {
    MessageBox(NULL,L"Failed to get the Address",NULL,NULL,NULL);
    }
    ...
    }
    

    f1 ist immer NULL.
    Was mache ich falsch?



  • was mache ich falsch?

    du benutzt eine Klasse



  • _o schrieb:

    was mache ich falsch?

    du benutzt eine Klasse

    Zum verständnis: C++ beherrscht ja Überladung und Namensräume. Also muss der Linker ja wissen welche Funktion er aufrufen soll. Deswegen "verstümmelt" der Compiler die Funktionsnamen und bezieht in den Namen Parameter und Namensbereich (wobei eine Klasse hier auch ein Namensraum ist).
    Außerdem: exportierst du die (verstümmelten) Funktionen überhaupt?



  • exportieren?

    Kann ich auch irgendwie Klassen-Funktionen außerhalb aufrufen ?



  • normalerweise macht man es so das man eine normale C funktion hat die dann eine instanz der klasse erzeugt und zurückgibt



  • Könntest du mir schnell eine kkleines beispiel geben?

    Danke ❤



  • //Klasse.h
    #include "Klasse_fuer_exe.h"
    __declspec(dllexport) class foo_imp : public foo //__declspec ist MS-Spezifisch.
    //Wenn du kein VS nutzt, guck nach wies bei deinem Compi aussieht
    {
    public:
        foo();
        int foobar();
    };
    
    //Klasse.cpp
    //..
    //Implementierungen von foo_imp
    //...
    
    extern "C" __declspec(dllexport) foo *createfooinstance()
    {
        return (foo*)new foo_imp;
    }
    
    extern "C" __declspec(dllexport) void destroyfooinstance(foo *pointer)
    {
        delete pointer;
    }
    
    //Klasse_fuer_exe.h
    //Damit deine Exe den (abstrakten) Klassentyp kennt
    class foo
    {
    protected:
        int bar;
    public:
        foo() = 0;
        int foobar() = 0;
    };
    
    //main.cpp
    //...
    #include "Klasse_fuer_exe.h"
    
    typedef foo *(*createfooinstance_t)(void);
    typedef void (*destroyfooinstance_t)(foo *pointer);
    
    int main()
    {
        //...
        createfooinstance_t createinstance = (createfooinstance_t)GetProcAddress(hDLL, "createfooinstance");
        destroyfooinstance_t destroyinstance = (destroyfooinstance_t)GetProcAddress(hDLL, "destroyfooinstance");
        //...
        foo *instance = createinstance();
        //...
        destroyinstance(instance);
        //...
    }
    

    Editiert, hoffe jetzt ist es richtig.



  • Das dllimport führt das Laden der DLL per LoadLibrary ad absurdum, da die DLL dann ja trotzdem fix bei Programmstart geladen wird.

    Es geht aber, wenn "createfooinstance" nen Zeiger auf eine abstrakte Basisklasse zurückgibt, die nur aus lauter "virtual pure" Memberfunktionen besteht. (Dann braucht man nämlich das "dllimport" nimmer um sie aufzurufen).



  • Dafür wird noch eine destroyfooinstance(..) Funktion benötigt.



  • Ja, die destroy Fkt. fehlt. Hab ich vergessen.
    Das bei dllimport war ich mir, wie gesagt, nicht sicher. Bis jetzt hab ich DLLs die Klassen enthielten nach diesem Schema aufgebaut:

    //Dll_Klasse.h
    #ifdef BUILD_DLL
    #define DLL __declspec(dllexport)
    #else
    #define DLL __declspec(dllimport)
    #endif
    
    DLL class foo
    {
    //...
    };
    

    Und dynamisch Laden hab ich bis jetzt nur einzelne Funktionen gemacht. Ich werd mal mein Beispiel editieren.


  • Mod

    Wenn Du ein virtuelles Interface benutzt ist das unnötig wie es hustbaer schon geschrieben hat.


Anmelden zum Antworten