DLLs aufrufen und dessen Funktionen ausführen



  • Dieser Thread wurde von Moderator/in HumeSikkins aus dem Forum C++ in das Forum WinAPI verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • chrische5 schrieb:

    Hallo

    Wie kann ich mehrere Klassen verteilt auf jeweils eine 1 Header und eine Sourcedatei nun zu einer dll zusammenfassen?

    Das mit dem Codebeispiel ist dabei sehr nützlich.

    chrische

    Du benutzt einfach bei der Deklaration der Klasse das Schlüsselwort __declspec(dllexport), Beispiel:
    CExample.hpp:

    class __declspec(dllexport) CExample
    {
       private:
         int m_iValue;
         // usw...
       public:
         CExample(void);
         ~CExample(void);
    
         int GetValue(void) const;
         void SetValue(int iNew);
         // usw...
    }
    

    CExample.cpp:

    CExample::CExample(void)
    {
       m_iValue = 0;
       // ...
    }
    
    CExample::~CExample(void)
    {
       // ...
    }
    
    int CExample::GetValue(void) const
    {
       // ...
       return (m_iValue);
    }
    
    void CExample::SetValue(int iNew)
    {
       m_iValue = iNew;
       // ...
    }
    

    Die Dateien einfach mit ins DLL-Projekt, compilieren und gut ist 😉 .

    PS: Hier darf natürlich NICHT das Schlüsselwort extern "C" verwendet werden!



  • Also als ich das, was "CodeFinder" geschrieben hat, hinzugefügt habe, hat gar nichts mehr funktioniert 😞
    Weiß denn keiner warum ich die geladene DLL Funktion nicht aufrufen kann?



  • SideWinder hat ja auch chrische geantwortet, nicht dir. Immer das selbe, wenn manche Leute mitten in einen Thread platzen, und dort ihre Fragen stellen...



  • Hey mikey: hast du das Problem schon behoben? Ich brauch Hilfe zum Thema DLLs 😞



  • Nee leider nicht, ich weis auch nicht an was es liegt 😞 Sorry



  • Vielleicht sollte das Problem nochmal beschrieben werden, mit Beispielcode!
    Im Prinzip gibt es 2 Sachen zu beachten:
    will man eine Klasse in eine DLL packen, so kann diese DLL nicht mehr dynamisch sondern nur noch statisch gelinkt werden (ja mit ein paar Assembler tricks kann man das umgehen, aber das ist nicht Sinn des Erfinders). Dabei werden die Funktionsnamen geändert (name-mangling) damit keiner auf die Idee kommt, direkt eine Funktion auszuführen.
    Will man stattdessen einfach nur irgendwelche Funktionen in eine DLL packen, die von verschiedenen Programmiersprachen benutzt werden können, so muss man dieses name-mangling ausschalten (mit extern "C").

    DLLMain braucht man nicht unbedingt, nur wenn man explizit auf das Laden, Entladen der DLL reagieren möchte.

    Einfaches Beispiel für eine DLL die eine kleine Funktion exportiert:

    extern "C" __declspec(dllexport) void test()
    {
    MessageBox(NULL, "Hello World", "", MB_OK);
    }
    

    Oder hab ich jetzt auf die falsche Frage reagiert bzw. war das gar nicht die Frage?!

    PS: obiges Beispiel gilt nur für MSVS, keine Ahnung wie die Syntax für andere Compiler lautet.



  • Du scheinst dich mit DLLs aus zu kennen, dann kann ich dich ja noch mal direkt fragen, ob du mir einen (so einfach wie möglich, aber gerne mit Beschreibung), Beipsiel Code schreiben könntest der einmal eine Funktion als DLL exportiert und ein Beispiel Code der diese Funktion aus der DLL wieder importiert!
    Würde mich über die zwei BeispielCodes echt freuen, Danke! 🙂



  • Die Exportierung habe ich oben beschrieben - Du erstellt einfach ein Win32 Projekt, dann unter den Einstellungen wählst du eine DLL aus und haust die oben beschriebene Fkt. in eine CPP Datei und voila, die DLL ist fertig (angenommen Du arbeitest mit VS2005)

    Die DLL kann entweder statisch oder dynamisch geladen werden. Ich werde jetzt erstmal auf die dynamische Variante eingehen:

    irgendwo in der main:

    HMODULE hDLL = LoadLibrary("Dllname.dll");
    void (*pfunc)() = (void (*)()) GetProcAddress(hDLL, "test");
    pfunc();
    

    Damit wird dann die test() Funktion in der DLL aufgerufen. Achtung, es wurde keine Fehlerüberprüfung durchgeführt...
    Wichtig ist nur, dass die DLL auch auffindbar ist 🙂 Sonst liefert LoadLibrary() NULL.

    Logisch soweit?



  • Cool! Danke "pub00515"! 🙂

    Hat funktioniert und war super leicht!

    Gruß LukasBanana



  • Da empfiehlt sich auch ein typedef zu verwenden. Macht die ganze Sache übersichtlicher 😉 .



  • CodeFinder schrieb:

    Da empfiehlt sich auch ein typedef zu verwenden. Macht die ganze Sache übersichtlicher 😉 .

    Vielleicht so?

    typedef extern "C" __declspec(dllexport) DLLexport;
    

    Gruß LukasBanana



  • Nee dafür benutzt Du besser ein #define.

    Also

    #define DLLEXPORT __declspec(dllexport)
    

    Was Codefinder vermutlich meint, sind typedefs für die Funktionspointer.
    z.B.

    typedef void (*voidfunc)();
    

    Dann kannst Du schreiben:

    voidfunc pfunc = (voidfunc) GetProcAddress(...)
    

    macht die Sache wesentlich übersichtlicher wenn der Prototyp länger wird. Oder man es oft benutzt :-).



  • Hehe, ne so (sry, hätte das Bsp sofort posten sollen):

    typedef void (*PFUNCTION)(void); // 'PFUNCTION' wird jetzt wie ein Typ behandelt, also bspw. wie int
    HMODULE hDLL = LoadLibrary(TEXT("Dllname.dll")); // DLL laden
    if(hDLL != NULL) // Prüfen, ob DLL erfolgreich geladen werden konnte
    {
       // Funktionszeiger-Variable anlegen und Adresse der Funktion in der DLL ermitteln:
       PFUNCTION pFunction = reinterpret_cast<PFUNCTION>(GetProcAddress(hDLL, "test"));
       if(pFunction != NULL) // Wichtig: Konnte die Adresse der Funktion erfolgreich ermittelt werden ? Falls nein, darf die Funktion nicht aufgerufen werden, sonst würde es hier eine Access-Violation geben!
          pFunction(); // Erfolgreich ermittelt, also aufrufen!
    }
    


  • Also so:

    /* ... */
    typedef (void (*)()) voidfunc;
    typedef (int (*)()) intfunc;
    typedef (float (*)()) floatfunc;
    /* ... */
    void (*MyFunc)() = voidfunc GetProcAddress(hDLL, "MyDLLFunction");
    

    Gruß LukasBanana



  • @pub00515: Jupp genau 👍 .



  • LukasBanana schrieb:

    Also so:

    /* ... */
    typedef (void (*)()) voidfunc;
    typedef (int (*)()) intfunc;
    typedef (float (*)()) floatfunc;
    /* ... */
    void (*MyFunc)() = voidfunc GetProcAddress(hDLL, "MyDLLFunction");
    

    Gruß LukasBanana

    Ne der Name des Typs muss direkt dem '*' folgen.
    ➡

    /* ... */
    typedef (void (*voidfunc)());
    typedef (int (*intfunc)();
    typedef (float (*floatfunc)());
    /* ... */
    
    voidfunc MyFunctionPointer;
    MyFunctionPointer = (voidfunc)GetProcAddress(hDLL, "MyDLLFunction");
    

    Siehe auch mein Beispiel oben.



  • Achso, danke ich hab`s jetzt glaub ich kappiert! 👍
    Danke an alle 🙂

    Gruß LukasBanana


Anmelden zum Antworten