Erstellen und einbinden einer DLL



  • Hi!

    Ich möchte eine DLL schreiben (noch nie gemacht) und wie du dir denken kannst krieg ich es nicht hin. Ich hab mich mal so durch die Hilfe gewühlt und mir was zusammengebastelt.

    Beim linken spuckt er folgende Meldung aus:
    ***********************************************************************
    ------ Erstellen gestartet: Projekt: DLLTest, Konfiguration: Debug Win32 ------

    Verknüpfen...
    DLLTestView.obj : error LNK2019: Nicht aufgelöstes externes Symbol '"__declspec(dllimport) double __cdecl EvalOvality(double,double)" (__imp_?EvalOvality@@YANNN@Z)', verwiesen in Funktion '"public: void __thiscall CDLLTestView::OnLButtonDown(unsigned int,class CPoint)" (?OnLButtonDown@CDLLTestView@@QAEXIVCPoint@@@Z)'
    Debug/DLLTest.exe : fatal error LNK1120: 1 unaufgelöste externe Verweise
    ***********************************************************************

    Mein Code sieht etwa wie folgt aus:

    ***********************************************************************
    ------Header File der DLL-------------------

    #define DllExport __declspec( dllexport )
    extern "C"
    {
    class CRundheitDLLApp : public CWinApp
    {
    public:
    CRundheitDLLApp();
    public:
    virtual BOOL InitInstance();
    DECLARE_MESSAGE_MAP()
    DllExport double EvalOvality(double IntensityX, double IntensityY);
    DllExport void Reset(void);
    DllExport void Parameter(double NomDiameter, double Speed);
    int m_valid;
    };
    }

    -----------Implementation im C File der DLL-------------
    double CRundheitDLLApp::EvalOvality(double IntensityX, double IntensityY)
    { .... }

    void CRundheitDLLApp::Reset(void)
    { .... }

    void CRundheitDLLApp::Parameter(double NomDiameter, double Speed)
    { .... }

    -------------Header des Programms welches die DLL benutzt-----

    ...
    #define DllImport __declspec( dllimport )
    DllImport double EvalOvality(double IntensityX, double IntensityY);
    ....
    *******************************************************************

    Meine Umgebung:
    WinXP, VSC++ .NET

    Ist sicherlich ganz einfach aber ich bin am Ende .... keine Ahnung ... 😞

    Vielen Dank für deine Mühe.



  • -------------Header des Programms welches die DLL benutzt----- 
    
    #define DllImport __declspec( dllimport ) 
    class DllImport CRundheitDLLApp : public CWinApp 
    { 
    public: 
    CRundheitDLLApp(); 
    public: 
    virtual BOOL InitInstance(); 
    DECLARE_MESSAGE_MAP() 
    double EvalOvality(double IntensityX, double IntensityY); 
    void Reset(void); 
    void Parameter(double NomDiameter, double Speed); 
    int m_valid; 
    }; 
    ------Header File der DLL------------------- 
    
    #define DllExport __declspec( dllexport ) 
    class DllExport CRundheitDLLApp : public CWinApp 
    { 
    public: 
    CRundheitDLLApp(); 
    public: 
    virtual BOOL InitInstance(); 
    DECLARE_MESSAGE_MAP() 
    double EvalOvality(double IntensityX, double IntensityY); 
    void Reset(void); 
    void Parameter(double NomDiameter, double Speed); 
    int m_valid; 
    };
    




  • Ich hab Code abgeändert wie Sovok es mir empfohlen hat. Nun bekomme ich folgende Meldung.

    ...
    Kompilieren...
    DLLTestView.cpp
    d:\DLLTest\DLLTestView.cpp(105) : error C3861: 'EvalOvality': Bezeichner wurde auch mit einer argumentbezogenen Suche nicht gefunden
    Generieren von Code...
    .....

    Er kennt einfach die Funktion nicht 😞

    Muss ich noch irgendwie sagen welche DLL er laden muss um die Funktion zu finden? Eine Art include oder etwas in der Richtung. 😕



  • zeig mal die zeile in der der fehler auftritt



  • Der Aufruf sieht wie folgt aus:

    void CDLLTestView::OnLButtonDown(UINT nFlags, CPoint point)
    {
    double f = EvalOvality(0.5,0.2);

    CView::OnLButtonDown(nFlags, point);
    }



  • entweder isses ein leichtsinnsfehler oder du solltest noch n bissi mehr c++ lernen bevor du dlls erstellst

    double f = EvalOvality(0.5,0.2); 
    
    double f = CRundheitDLLApp().EvalOvality(0.5,0.2);
    

    kleiner feiner unterschied 😉



  • Ja da hast du sicher recht aber man kann sich nicht immer aussuchen was man porgrammieren muss. Chef sagt:"Programmier DLL!" -> Suzi programmiert DLL

    Jetzt hab ich den folgenden Fehler in der selben Zeile erhalten:

    Kompilieren...
    DLLTestView.cpp
    d:\DLLTest\DLLTestView.cpp(105) : error C2248: 'CRundheitDLLApp::EvalOvality': Kein Zugriff auf protected Element, dessen Deklaration in der Klasse "CRundheitDLLApp" erfolgte
            d:\DLLTest\DLLTestView.h(14): Siehe Deklaration von 'CRundheitDLLApp::EvalOvality'
            d:\DLLTest\DLLTestView.h(8): Siehe Deklaration von 'CRundheitDLLApp'
    

    Ich kann nicht zugreifen. Hat das etwas mit dem Dokument/View Konzept zu tun?



  • ne is simpel

    #define DECLARE_MESSAGE_MAP() \
    private: \
    	static const AFX_MSGMAP_ENTRY _messageEntries[]; \
    protected: \
    	static AFX_DATA const AFX_MSGMAP messageMap; \
    	static const AFX_MSGMAP* PASCAL _GetBaseMessageMap(); \
    	virtual const AFX_MSGMAP* GetMessageMap() const; \
    

    d.h. deine klasse sieht so aus

    class DllExport CRundheitDLLApp : public CWinApp 
    { 
    public: 
    CRundheitDLLApp(); 
    public: 
    virtual BOOL InitInstance();
    
    private:
    	static const AFX_MSGMAP_ENTRY _messageEntries[];
    protected:
    	static AFX_DATA const AFX_MSGMAP messageMap;
    	static const AFX_MSGMAP* PASCAL _GetBaseMessageMap();
    	virtual const AFX_MSGMAP* GetMessageMap() const;
    //also is EvalOvality protected
    double EvalOvality(double IntensityX, double IntensityY); 
    void Reset(void); 
    void Parameter(double NomDiameter, double Speed); 
    int m_valid; 
    };
    

    schreib es einfach so

    class DllExport CRundheitDLLApp : public CWinApp 
    { 
    public: 
    CRundheitDLLApp(); 
    public: 
    virtual BOOL InitInstance();
    
    DECLARE_MESSAGE_MAP()
    
    public:
    double EvalOvality(double IntensityX, double IntensityY); 
    void Reset(void); 
    void Parameter(double NomDiameter, double Speed); 
    int m_valid; 
    };
    


  • Hat funktioniert jetzt linkt das Programm. Beim Aufruf der DLL Funktion gibt es jedoch einen Laufzeitfehler:

    Debug Assertion Failed
    File: appcore.cpp
    Line: 235
    ....

    Langsam hab ich ein schlechtes Gewissen weil ich keinen einzigen Schritt alleine schaffe 😡 . Ich bin dir wirklich sehr dankbar.

    Ich hab aber gemerkt das das ganze einfach zu kompliziert ist für mich. Deshalb versuch ich jetzt eine Variante ohne MFC nur ein simples Min32-Projekt.

    Hier mein Code (ich hab versucht alles so einfach wie möglich zu machen):

    //[b]DLL C-File[/b] 
    //LIB.cpp : Definiert den Einstiegspunkt für die DLL-Anwendung.
    
    #include "stdafx.h"
    #include "windows.h"
    #include "lib.h"
    
    BOOL APIENTRY DllMain( HANDLE hModule, 
                           DWORD  ul_reason_for_call, 
                           LPVOID lpReserved
    					 )
    {    return TRUE;    }
    
    RundDLL::RundDLL() {}
    
    int Funktion()
    {    return 5; }
    
    //[b]DLL Header-File[/b]
    //lib.h
    
    #ifdef _cplusplus
    #define DllExport extern "C" __declspec(dllexport)
    #else
    #define DllExport __declspec(dllexport)
    #endif
    
    class DllExport RundDLL 
    {
    public:
    	RundDLL();
    	int Funktion();
    };
    
    //[b]Testprogramm[/b]
    ...
    #include "TEST.h"
    
    int APIENTRY _tWinMain(HINSTANCE hInstance,
                         HINSTANCE hPrevInstance,
                         LPTSTR    lpCmdLine,
                         int       nCmdShow)
    {
    
    	int g = RundDLL().Funktion(); //eingefügt
    ....
    
    //[b]Testprogramm Header File[/b]
    #pragma once
    
    #include "resource.h"
    
    #define DllImport __declspec( dllimport ) 
    class DllImport RundDLL 
    {
    public:
    	RundDLL();
    	int Funktion();
    };
    

    Jetzt hab ich wieder ein unaufgelöstes Symbol 😞

    ....
    Kompilieren...
    TEST.cpp
    Verknüpfen...
    TEST.obj : error LNK2019: Nicht aufgelöstes externes Symbol '"__declspec(dllimport) public: int __thiscall RundDLL::Funktion(void)" (__imp_?Funktion@RundDLL@@QAEHXZ)', verwiesen in Funktion '_WinMain@16'
    Debug/TEST.exe : fatal error LNK1120: 1 unaufgelöste externe Verweise
    .....

    🙄



  • Existiert in deinem DLL-Projekt eine *.def - Datei ?



  • Nein eine .def Datei hab ich nicht. Aber es sollte auch ohne sowas gehen wenn ich das richtig verstanden habe.



  • is nich kompliziert... man muss sich nur dran gewöhnen
    du hast es sogar fast geschafft 🙂

    int Funktion()
    {    return 5; }
    
    muss heissen 
    
    int RundDLL::Funktion()
    {    return 5; }
    

    dann noch folgendes:
    -öffne dein tesprogramm
    -rechtsklick im arbeitsbereich->add files to folder->füg aus dem Debug/Release ordner deiner dll die datei dllname.lib hinzu

    jetzt sollte es tun

    edit: ja geht ohne def
    wobei ich defs einfacher finde



  • Ich hab es ohne diese *.lib Datei versucht aber dann findet er den Entrypoint nicht. Muss diese Datei immer im gleichen verzeichnis liegen wie die DLL damit es funktioniert?

    Was hat diese *.lib für eine Funktion?



  • die lib muss du mit deinem programm linken
    zur laufzeit brauchst du die lib nich

    in der lib stehen infos über die dll damit das programm weiss welche funktionen verfügbar sind und wie es sie aufrufen kann

    die dll muss entweder im gleiche verzeichnis wie die exe(falls aus vc gestartet reicht auch das projektverzeichnis), in windows/system32 oder in nem ordner der in der PATH umgebungsvariable angegeben is



  • Wenn ich nun aber eine DLL gebrauchen möchte, von der ich den Sourcecode und die *.lib Datei nicht habe sonder nur die fertige DLL? Wie kann ich dann trotzdem auf die Funktionen zugreifen?



  • in etwa so

    typedef int(func*)(int) libfunc;
    
    //dll laden
    HANDLE Lib=LoadLibrary("libname.dll");
    //funktion laden
    libfunc Func=(libfunc)GetProcAddress(Lib);
    //funktion aufrufen
    Func(100);
    


  • Super hat funktioniert ich hab jetzt eine eigene DLL 😃

    Aber jetzt nochmal zu der DLL bei der ich kein *.lib File habe. Ich habe eine Funktion die wie folgt definiert worden ist.

    __declspec(dllexport) int GetDefaultPrinter( char *buffer, int len );

    Mein Code dazu um die Funktion aus der DLL zu laden sieht nun wie folgt aus:

    HINSTANCE hLib = LoadLibrary("MSDPrintDll.dll");
    
    typedef int (WINAPI *PFN_PRINTER)(char*, int);
    PFN_PRINTER pfn_printer = (PFN_PRINTER) GetProcAddress(hLib, "GetDefaultPrinter");
    
    char * text = "";
    int i = pfn_printer(text, 5 );
    

    Beim kompilieren hat er kein Problem ... läuft alles glatt. Wenn ich das Programm laufen lasse, kommt jedoch folgender Laufzeitfehler:

    Run-Time Check Failure #0 - The value of ESP was not properly saved
    across a function call.  This is usually a result of calling a function
    declared with one calling convention with a function pointer declared with a
    different calling convention.
    

    Ich bin mir aber sicher, dass der Funktionskopf stimmt! 😕



  • #define WINAPI __stdcall

    __stdcall is die standard aufrufkonvention von windows
    entweder du schreibst es bei export und import oder bei keinem von beiden


Anmelden zum Antworten