Probleme beim Einbinden eigener Dll



  • Hallo zusammen,

    ich habe ein Problem mit dem Einbinden einer selbstgeschriebenen Dll. Aus diese importiere ich eine einzelne Funktion mittels dieses Statements:

    __declspec(dllimport)BOOL CheckString(LPCTSTR);
    

    Ich habe, bevor ich das Paket ausgeliefert habe, die Anwendung auf Windows XP sowie Windows2000 Rechnern erfolgreich getestet.

    Jetz habe ich das Problem, dass auf einer Maschine die Dll gar nicht erst angezogen wird.
    Testweise habe ich mir einen Useraccount angelegt, auf dem ich alle Rechte entzogen hatte. Dennoch lief die Anwendung einwandfrei.

    Zur Info, die Dll liegt im selben Verzeichnis wie die aufrufende Anwendung. Muss bzw. kann ich den Ort der Dll explizit angeben?
    Woran kann es liegen, dass die Dll nicht angezogen wird?

    Ich weiß nicht, welche Informationen ihr noch benötigt, sagt mir da bitte wenn ihr mehr Infos gibt. Ich frage erstmal so, falls es grundlegende Sachen gibt, die man als Anfänger in dem Bereich falsch machen kann.

    Gruß und danke...



  • Woran kann es liegen, dass die Dll nicht angezogen wird?

    Weil sich eine DLL nur mit einem MS zertifizierten DLL-Drehmomentschlüssel anziehen lässt. Ist auch gut so, sonst könntest du die dabei ja beschädigen.

    Ok, im Ernst, ich habe keine Ahnung was du mit "anziehen" meinst. Wie wird die DLL denn überhaupt geladen? Über LoadLibrary, oder implizit wenn das Programm startet? Blubb?



  • Wenn das Programm startet. Durch den Aufruf Dllimport eben..

    Ja sorry, ich sage dazu anziehen (also laden, zum Programmcode hinzuziehen) - aber ich bin damit nicht allein 🙂



  • 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.



  • Also wenn das

    DrOetker schrieb:

    Wenn das Programm startet. Durch den Aufruf Dllimport eben..[...]

    die Antwort darauf

    hustbaer schrieb:

    [...]Wie wird die DLL denn überhaupt geladen? Über LoadLibrary, oder implizit wenn das Programm startet?[...]

    ist, dürfte das IMHO daran liegen, das du deine DLL in keinster Weise lädst (oder anziehst 😃 😃 ...).
    Denn das Schlüsselwort __declspec(dllimport) lädt doch kein DLL-Modul in dein Adressraum deines Programms.

    Mach das am besten, wie hustbaer schon erwähnte, mit LoadLibrary 😉 .



  • Also, so wie ich die Tutorials in die Richtung bisher verstanden habe, impliziert ein Import der Funktion mittels des Dllimport Statements, dass die Dll zum Programmstart geladen wird.
    Hier soll die Dll dann später im selben Verzeichnis wie die Anwendung liegen, damit es läuft. Ich habe das Programm mittels Verweis auf die zugehörige Lib kompiliert.

    Loadlibrary ist doch ein dynamisches Nachladen der Dll zur Laufzeit oder nicht? So wie ich das verstanden habe, sind das zwei paar Schuhe? Ich lasse mich aber natürlich gern belehren!

    Wikipedia schrieb:

    Eine DLL einbinden / aufrufen [Bearbeiten]

    DLL Funktionen können einfach aufgerufen werden, nachdem man sie mit der Funktion __declspec(dllimport) importiert hat.

    #include <windows.h>
    #include <stdio.h>
    
    // Importieren der Funktion aus der oben erstellten DLL
    
    extern "C" __declspec(dllimport)double AddNumbers (double a, double b);
    
    void main () {
            // Aufrufen der externen Funktion
            double result = AddNumbers(1, 2);
            printf("Das Ergebnis ist: %f\n", result);
    }
    

    Zu beachten ist, dass der Linker die LIB Datei benötigt und dass sich die DLL-Datei im selben Ordner wie das Programm, das sie aufrufen soll, befinden sollte. Die LIB Datei wird vom Linker benötigt, da diese - ähnlich einer Header Datei - die Funktionsprototypen enthält.

    Was verstehe ich nun falsch? In dem Beispiel wird die Dll doch auch nicht explizit in den Adressraum geladen (obwohl ich mich auch schon darüber gewundert habe)...

    😕 😕 😕



  • DrOetker schrieb:

    Loadlibrary ist doch ein dynamisches Nachladen der Dll zur Laufzeit oder nicht? So wie ich das verstanden habe, sind das zwei paar Schuhe? Ich lasse mich aber natürlich gern belehren!

    Das ist richtig. Es gibt auf der einen Seite das statische Linken und das dynamische Binden ( ➡ LoadLibrary) 😉 .

    Normalerweise werden aber alle zu importierenden Funktionen etc. in einen Dll-Header ausgelagert, der dann inkludiert wird.

    Hier ist nochmal ein Tutorial ➡ Creating And Using DLLs.



  • Okay soweit.
    Dann werde ich das so umsetzen.
    Kann mir jetzt noch jemand sagen, warum die Dll denn auf fast allen Rechnern mit dem beschriebenen Aufruf korrekt geladen wird?!



  • Wie sieht denn der Fehler überhaupt aus? Bekommst du vom OS eine Meldung dass die Funktion "foo" in der DLL "bar" nicht gefunden werden konnte? Oder dass die DLL "bar" nicht gefunden werden konnte? Oder startet das Programm bloss funktioniert dann nicht?

    Und wie heisst die DLL - könnte der Name mit etwas kollidieren was vielleicht irgendeine "injected" DLL ist?

    Also wenn du "statisch" gegen eine DLL linkst, also wenn du das ".lib" File der DLL beim Linken des Programmes angibst (also ohne LoadLibrary halt), dann funktioniert das normalerweise schon wenn die DLL im gleichen Verzeichnis wie das Programm liegt.



  • Also, der Fehler, der auftritt ist, dass das Programm (eine win32 Konsolenanwendung) gar nicht erst startet. Ich bekomme keine Meldung vom OS. Was ist eine injected Dll? Also die Dll ist mit dem Namen auf dem OS defintiv noch nicht vorhanden!



  • Hallo zusammen!

    Ich habe auch ein Problem beim Einbinden einer DLL und bevor ich ein neues Thema anfange, dachte ich mir, mach ich´s mal mit hier rein.

    Die Fehlermeldung die ich bekomme ist "The value of ESP was not properly saved across a function call."

    Soweit ich das jetzt verstehe stimmt wohl irgendwas mit den Funktionssignaturen nicht.

    Erstmal der Quellcode für die DLL:

    #pragma pack(1)
    
    #include <stdio.h>
    
    #ifndef	__CtoD_DLL
    #define	__CtoD_DLL
    
    typedef unsigned char byte;
    
    struct BildDatenDelphi {
    	int BildBreite;
    	int BildHoehe;
    	//byte *BildArray;
    };
    
    _declspec(dllexport) UINT DelphiToC(struct BildDatenDelphi *BildDaten);
    
    _declspec(dllexport) UINT DelphiToC(struct BildDatenDelphi *BildDaten)
    {
    	FILE *fp;
    
    	if((fp=fopen("OutPutDLL.txt","wt"))==NULL) return 1;
    
    	fprintf(fp, "Delphi Daten\n");
    	fprintf(fp, "Bildbreite:\t%i\n", BildDaten->BildBreite);
    	fprintf(fp, "Bildhoehe:\t%i\n", BildDaten->BildHoehe);
    
    	fclose(fp);
    
    	return 0;
    }
    
    #endif
    

    und hier der Quellcode mit dem ich die DLL aufrufe:

    #pragma pack(1)
    
    #include <stdio.h>
    #include <windows.h>
    
    #define THE_DLL "DtoC_DLL.dll"
    
    typedef unsigned char byte;
    
    struct BildDatenDelphi {
    	int BildBreite;
    	int BildHoehe;
    	//byte *BildArray;
    };
    
    typedef UINT (CALLBACK *LPFNDLLFUNC1)(struct BildDatenDelphi *ABildDatenPtr);
    
    HINSTANCE hDLL;
    LPFNDLLFUNC1 lpfnDllFunc1;    // Function pointer
    UINT  uReturnVal;
    
    int main (void)
    {
    	struct BildDatenDelphi BildDaten;
    	struct BildDatenDelphi *BildDatenPtr;
    
    	BildDaten.BildBreite = 600;
    	BildDaten.BildHoehe = 480;
    
    	BildDatenPtr = &BildDaten;
    
    	hDLL = LoadLibrary(THE_DLL);
    	if(hDLL == NULL)
    	{
    		return 1;
    	}
    	else
    	{
    		lpfnDllFunc1 = (LPFNDLLFUNC1)GetProcAddress(hDLL,"DelphiToC");
    		if (!lpfnDllFunc1)
    		{
    			// handle the error
    			FreeLibrary(hDLL);       
    			return 2;
    		}
    		else
    		{
    			// call the function
    			uReturnVal = lpfnDllFunc1(BildDatenPtr);
    
    		}
    	}
    
    	FreeLibrary(hDLL);
    
    	return 0;
    }
    

    Die gute Nachricht ist, dass die DLL auch wirklich aufgerufen wird und auch die "OutPutDLL.txt" Datei mit korrekten Werten schreibt.
    Aber bei Rückkehr zum Aufrufprogramm fliegt mir das Ganze um die Ohren.

    Es gibt zwar schon eine ganze Menge von Beschreibungen wie DLL´s explizit eingebunden werden, aber niemand hat mal ein Beispiel mit einem struct pointer 😞 .

    Wahrscheinlich ist es ein typischer Anfängerfehler, würde mich aber riesig freuen, wenn mir jemand helfen könnte.

    Danke schon mal!

    PS: das "#pragma pack(1)" steht nur drin, weil ich die DLL mal aus einer Delphianwendung aufrufen möchte.



  • so jetzt hab ich die Lösung selber gefunden.

    CALLBACK ist definiert als __stdcall
    allerings muß ich wohl die DLL Funktion mit __cdecl aufrufen.
    also so:

    typedef int (__cdecl *LPFNDLLFUNC1)(struct BildDatenDelphi *ABildDaten);
    

    allerdings hatte ich schon versucht die Funktion in der DLL mit
    " extern "C" " zu deklarieren, hat aber nicht funktioniert.

    Falls jemand Plan hat, kann er ja was über diese "mysteriösen" Aufrufkonventionen erklären.

    so long


Log in to reply