Astasor Geschrieben 29. August 2013 Geschrieben 29. August 2013 Hallöchen, ich konnte bei Problemen immer auf das Board vertrauen und deshalb komme ich jetzt wieder zu euch zurück Ich habe eine DLL erstellt und würde sie gerne in einem anderen Projekt nutzen. Mithilfe von LoadLibrary konnte ich die DLL auch laden, aber GetProcAccess gibt mir nicht die Addresse meiner Function aus, obwohl ich sie mit __declspec(dllexport) aus der DLL exportiert und __declspec(dllimport) in das Zweitprogramm importiert habe. Hier mal mein Code. Ich nehm das PHP-Tag, da es dort schönes Syntax-Coloring gibt. Die erste Zeile ist der jeweilige Name der Datei. Hier ist der Code von meiner DLL. #dll.h #ifndef _DLL_H_ #define _DLL_H_ #if BUILDING_DLL # define DLLIMPORT __declspec (dllexport) #else /* Not BUILDING_DLL */ # define DLLIMPORT __declspec (dllimport) #endif /* Not BUILDING_DLL */ #include <string> class DLLIMPORT DllClass { public: DllClass(); virtual ~DllClass(void); private: }; __declspec(dllexport) std::string testDll(); #endif /* _DLL_H_ */ [/PHP] [PHP] #dllmain.cpp #include "dll.h" #include <windows.h> #include <string> DllClass::DllClass() { } DllClass::~DllClass () { } __declspec(dllexport) std::string testDll(); BOOL APIENTRY DllMain (HINSTANCE hInst /* Library instance handle. */ , DWORD reason /* Reason this function is being called. */ , LPVOID reserved /* Not used. */ ) { switch (reason) { case DLL_PROCESS_ATTACH: break; case DLL_PROCESS_DETACH: break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; } /* Returns TRUE on success, FALSE on failure */ return TRUE; } std::string testDll(){ std::string test="Die DLL wurde erfolgreich eingebunden."; return test; } Hier ist der Code von meinem Zweitprogramm, indem ich die DLL nutzen will. #TestDll.cpp #include "./TestDll.h" #include <windows.h> TestDll::TestDll(){ HINSTANCE hInstance; hInstance = ::LoadLibrary("./../Test/DLL/Test.dll"); pDllFunction = (LPFNDLLFUNC1*)::GetProcAddress((HMODULE)hInstance,"testDll"); } bool TestDll::CallDllFunction(){ if(pDllFunction){ return true; } else{ return false; } } [/PHP] [PHP] #TestDll.h #ifndef _TESTDLL_H_ #define _TESTDLL_H_ #include <string> class TestDll{ private: typedef std::string LPFNDLLFUNC1(); LPFNDLLFUNC1 *pDllFunction; public: TestDll(); bool CallDllFunction(); }; #endif #main.cpp #include <cstdlib> #include <iostream> #include <windows.h> #include "./TestDll.h" #include <string> using namespace std; __declspec(dllimport) string testDll(); int main(int argc, char *argv[]) { TestDll DllTest; cout<<DllTest.CallDllFunction()<<endl; system("PAUSE"); return EXIT_SUCCESS; } [/PHP] Danke das ihr bis hier her gelesen habt. Jetzt noch mal konkret meine Fragen: Was mache ich hier falsch? Sind die Präprozessordirektiven in der dll.h korrekt? Stimmt das typedef in der TestDll.h so, wie es zur Zeit dasteht? Vielen Dank mfg Astasor Zitieren
Klotzkopp Geschrieben 29. August 2013 Geschrieben 29. August 2013 Schau dir mal mit dem Dependency Walker an, wie die in der DLL exportierte Funktion wirklich heißt. Da der Name der Funktion wegen der Möglichkeit zur Überladung kein ausreichendes Unterscheidungskriterium ist, muss sich der Compiler etwas anderes einfallen lassen. Er tut dies in Form des sogannten "name mangling". Dabei werden Rückgabetyp und Parametertypen auf bestimmte Art und Weise mit dem Funktionsnamen zu einem neuen Namen verwurstet. Dieser neue Name ist es, den du bei GetProcAddress angeben müsstest. Benutzt du bewusst Run-Time Dynamic Linking? Würde Load-Time Dynamic Linking ausreichen? Zitieren
Astasor Geschrieben 29. August 2013 Autor Geschrieben 29. August 2013 (bearbeitet) Das mit dem Dependency Walker war ein wirklich guter Tipp. Meine Funktion hatte einen Namen mit Buchstabengewürfel drum rum. Dazu kam noch ein _. Auf deine erste Frage: Nein. Ich habe gegoogelt wie es geht und bin dabei auf diese Funktionen gestoßen. Was ist der Unterschied zwischen den beiden Verfahren? Bearbeitet 29. August 2013 von Astasor Zitieren
Klotzkopp Geschrieben 30. August 2013 Geschrieben 30. August 2013 Run-Time Dynamic Linking (Windows) Was du machst, ist Run-Time Dynamic Linking. Vorteil: Du kannst auch mit DLLs umgehen, die du nicht kennst, oder die sogar fehlen. Dafür musst du dir aber alles selbst heraussuchen. Du brauchst dafür aber weder __declspec(dllimport) noch den Header der DLL. Deine Funktion CallDllFunction wird übrigens ihrem Namen nicht gerecht, sie ruft nichts auf, sondern prüft nur den Funktionszeiger. Load-Time Dynamic Linking (Windows) Mit Load-Time Dynamic Linking bricht dein Programm beim Start mit einem Fehler ab, wenn eine benötigte DLL fehlt. Dafür kannst du die exportierten Funktionen genauso aufrufen, als wären sie lokal definiert. Dazu musst du dein Programm gegen die kleine statische Bibliothek (.lib) linken, die mit der DLL erstellt wird, die sogenannte Importbibliothek, und den DLL-Header einbinden. Weiter brauchst du nichts. Zitieren
Astasor Geschrieben 30. August 2013 Autor Geschrieben 30. August 2013 Danke für deine Antwort. Ich hatte die Funtion auch erst anders geschrieben und sie dann wegen Testzwecken abgeändert. Danke für deinen Tipp mit dem kleinen nützlichen Zusatzprogramm. Nun kann ich endlich mit DLL's arbeiten. mfg Astasor Zitieren
Astasor Geschrieben 4. September 2013 Autor Geschrieben 4. September 2013 Ich habe noch eine Nachfrage bezüglich des "Name Mangling". Ich habe bereits danach gegoogelt, doch es scheint niemand je ernsthafte Anstrengungen unternommen zu haben, das zu unterbinden und die Funktionsnamen im Klartext verfügbar zu halten. Warum ist das so? Wenn ich eine DLL schreibe, gebe ich sie unter Umständen an jemand anderes weiter und es wäre toll, wenn Derjenige normale Funktionsnamen zum Aufrufen der exportierten Funktionen verwenden könnte und nicht so ein komisches Wortgewürfel. Zitieren
Klotzkopp Geschrieben 4. September 2013 Geschrieben 4. September 2013 Warum ist das so? Weil das Name Mangling in C++ nunmal notwendig ist. Der Name einer Funktion ist nur in C ein eindeutiges Unterscheidungsmerkmal. In C++ gibt es Überladung. Stell dir vor, deine DLL exportiert diese Funktionen: void foo(int); void foo(double);[/code] Wenn beide über den Namen "foo" exportiert werden, wie willst du sie unterscheiden? Wenn ich eine DLL schreibe, gebe ich sie unter Umständen an jemand anderes weiter und es wäre toll, wenn Derjenige normale Funktionsnamen zum Aufrufen der exportierten Funktionen verwenden könnte und nicht so ein komisches Wortgewürfel. Wenn man eine DLL weitergibt, benutzt man in aller Regel Load-Time Dynamic Linking, man liefert also Header und Importbibliothek mit aus. Damit sieht der Benutzer nichts vom Name Mangling. Wenn du absolut Run-Time Dynamic Linking benutzen musst, und deine Funktionen nicht überladen sind, dann definiere sie als extern "C", dann unterbleibt das Name Mangling. Zitieren
flashpixx Geschrieben 4. September 2013 Geschrieben 4. September 2013 Warum ist das so? Weil es im C++ Standard nicht standardisiert wurde, deshalb gibt man bei binären Daten dann Compiler & Linker mit an. Wenn ich eine DLL schreibe, gebe ich sie unter Umständen an jemand anderes weiter und es wäre toll, wenn Derjenige normale Funktionsnamen zum Aufrufen der exportierten Funktionen verwenden könnte und nicht so ein komisches Wortgewürfel. Weil nicht Du es lesen sollst, sondern die Maschine und außerdem musst Du dann auch einen Standard definieren. Und der Funktionsname reicht nicht, Du brauchst die Signatur der Funktion. Ich gebe aber mal den Hinweis darauf, dass bei C dieses entsprechend definiert wurde, da C++ den kompletten C Sprachsyntax umfasst, kann man die Einsprungspunkte als C Signaturen definieren und intern weiterhin C++ nutzen. Zitieren
Redmann.m Geschrieben 31. August 2014 Geschrieben 31. August 2014 Hallo, ich würde mich auch für die Erstellung von dll's interessieren. Jedoch vorerst mal für C da ich das gerade in meiner Umschulung durch nehme. So wirklich brauchbare Tutorials oder infos findet man aber nur zu C++. Ich arbeite mit Netneans und würde mich über ein paar Tipps und Stichworte zur Recherche freuen. Gruß Marcus Zitieren
flashpixx Geschrieben 31. August 2014 Geschrieben 31. August 2014 Ich arbeite mit Netneans und würde mich über ein paar Tipps und Stichworte zur Recherche freuen. Netbeans ist eine Java Komponente, was hat das mit DLLs zu tun? Zitieren
Redmann.m Geschrieben 31. August 2014 Geschrieben 31. August 2014 Netbeans ist eine IDE mit der man auch C/C++ Anwendungen entwickeln kann. Die Tatsache das Netbeans in und für Java geschrieben wurde macht es mir dennoch möglich auch C DLL Projekte anzulegen und zu entwickeln. Ich bräuchte nur einen Einstiegspunkt um mich darüber zu informieren wie ich explizit Funktionen in dll's auslagere und in einem C Programm einbinde und verwende. Leider finde ich nur Infos für C++. Gruß Marcus Zitieren
Klotzkopp Geschrieben 31. August 2014 Geschrieben 31. August 2014 Ich bräuchte nur einen Einstiegspunkt um mich darüber zu informieren wie ich explizit Funktionen in dll's auslagere und in einem C Programm einbinde und verwende. Leider finde ich nur Infos für C++.Es gibt da keine nennenswerten Unterschiede. Irgendwelche Besonderheiten zu Klassen, Namensräumen und Überladung kannst du ignorieren, weil es so etwas in C nicht gibt. Zitieren
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.