Wieso wird diese Funktion nicht gefunden?



  • huhu
    ich habe eine funktion in einer dll:
    dll.h

    #ifdef __DLLFILE_H
    #define __DLLFILE_H
    
    #ifdef BUILDDLL
     #define DLL_MODE
     	__declspec(dllexport)
    #else
     #ifdef BUILDAPP
      #define DLL_MODE
            __declspec(dllimport)
      #endif
     #endif
    
     extern "C"
     int DLL_MODE MyFunction();
    
     #endif
    

    dll.cpp

    pragma argsused
    int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
    {
    	return 1;
    }
    //---------------------------------------------------------------------------
    int MyFunction()
    {
        return 10;
    }
    

    Calling-Application

    #include <vcl.h>
    #pragma hdrstop
    #define BUILDAPP
    #include "Calling_App.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TForm1 *Form1;
    //---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)
    	: TForm(Owner)
    {
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
    HINSTANCE h = LoadLibrary("Project1.dll");
    typedef int (*pfunc)();
    pfunc myFunc;
    if(h!=NULL)
       {
           myFunc = (pfunc)GetProcAddress(h,"_MyFunction");
           if(myFunc!=NULL)
              {
                  int x = myFunc();
                  ShowMessage(String(x));
              }
           else
              ShowMessage("Funktion nicht gefunden");
       }
    else
       ShowMessage("Datei nicht gefunden");
    }
    //-----------------------------------------
    

    Er sagt mir immer, Funktion nicht gefunden Warum?
    Und wie kann ich einen funktionszeiger ohne typedef hier verwenden?



  • Hallo,

    Deine Funktion ist falsch definiert. Vergleiche mal Deklaration in dll.h mit Definition in dll.cpp.
    Wozu brauchst du eigentlich diese dll.h. Beim derzeitigen Stand deiner dll ist die unnötig.
    Also
    in die dll.cpp muß rein

    extern "C" __declspec(dllexport) int MyFunction()
    {
        return 10;
    }
    

    ohne typedef würde das so aussehen.

    int (*myFunc)();
    


  • oh ich dachte ich kann die defines aus der h auch verwenden, also eben dieses DLL_MODE! Geht wohl nicht!

    Und zu dem fkt zeiger ohne typedef

    int (*pfunc)();
    

    und wie benutze ich damit das GetProcAddress?

    int(*pfunc)()GetProcAddress(); //??
    


  • So

    myFunc = (int(*)())GetProcAddress();
    

    Nimm lieber das typedef. Das sieht übersichtlicher aus.



  • eine frage habe ich gleich noch: Kann ich auch VCL Koponenten (Forms) dynamisch aus einer DLL importieren? (über Funktion dann sicher oder?)



  • Ja, das geht auch.
    Lies dir doch vielleicht mal ein dll-Tutorial durch
    http://bcb-tutorial.c-plusplus.net/inhalt.html
    oder diesen Thread
    http://www.c-plusplus.net/forum/viewtopic-var-t-is-171798.html



  • ok, hab das so probiert:
    Form.cpp

    #include <vcl.h>
    #pragma hdrstop
    
    #include "Unit2.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TForm2 *Form2;
    //---------------------------------------------------------------------------
    __fastcall TForm2::TForm2(TComponent* Owner)
    	: TForm(Owner)
    {
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm2::Button1Click(TObject *Sender)
    {
    ShowMessage(Edit1->Text);	
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm2::FormClose(TObject *Sender, TCloseAction &Action)
    {
    Action = caFree;	
    }
    

    DLL.cpp

    #pragma argsused
    int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
    {
    	return 1;
    }
    //---------------------------------------------------------------------------
    extern "C" void __declspec(dllexport) ShowForm(TComponent* Owner)
    {
        Form2 = new TForm2(Owner);
        Form2->ShowModal();
    }
    

    Aufrufendes Programm

    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
    HINSTANCE h = LoadLibrary("Project1.dll");
    if(h)
       {
           typedef void (*pFunc)(TComponent*);
           pFunc CallingFunction;
           CallingFunction = (pFunc)GetProcAddress(h,"_ShowForm");
           if(CallingFunction)
              {
                  CallingFunction(Application);
              }
           else
              {
                  ShowMessage("Form kann nicht angezeigt werden");
              }
       }
    else
       {
           ShowMessage("Datei nicht gefunden");
       }
    FreeLibrary(h);
    }
    

    öffnet sich alles wunderbar, aber beim schließen der Form aus der DLL, bekomme ich eine Zugriffsverletzung!

    Wieso?
    Wer oder wo muss ich den speicher freigeben?



  • ok, bei ShowModal kann ihc danach gleich ein

    delete Form2;
    

    ausführen, aber was ist, wenn ich die Form nicht Modal anzeige?
    Da kommt der Zugriffsfehler!



  • Der Zugriffsfehler hat nichts mit dem delete zu tun. geh doch mal mit dem Debugger durch und schau nach wo der Zugriffsfehler kommt. Du solltest auch deiner dll-Form -Instanz nicht Application mitgeben. Übergib hier einfach 0. Bedenke, dass der Owner für das Löschen der Form zuständig ist.
    Also

    extern "C" void __declspec(dllexport) ShowForm()
    {
        Form2 = new TForm2(0); // jetzt bist du selbst für dein delete zuständig
        Form2->ShowModal();
        delete Form2;
    }
    

    Bei nichtmodalen Formen kannst du ja im OnClose-Event der Form Action=caFree setzen. Dann wird die Form beim Schließen aus dem Speicher entfernt. Hier solltest du aber aufpassen, dass du nicht die dll entlädtst wären die entsprechende Form noch zu sehen ist.



  • ok, es liegt daran, das schon das FreeLibrary kommt, bvor die Form Closed ist!
    Wie kann ich das Abfangen, da ja die aufrufende Anwendung von dem Form2 nix weiß!



  • Die einfachste Variante wäre, du entlädst die dll erst wenn du die Hauptanwendung beendest. Eine andere Lösung wäre es der Hauptanwendung mitzuteilen wenn sich die dll-Form schließt. Dies kann man über Windows-Botschaften oder auch eine CallBack-Funktion machen.


Anmelden zum Antworten