dll exportieren, statisch importieren, dynamisch importieren
-
Hier mal ein ungefragter Vorschlag, wie man ganz problemlos DLL-Funktionen exportieren und statisch oder dynamisch importieren kann.
Als Vorschlag für den DLL-Thread in der FAQHeader (für Ex- und Import zu verwenden)
/*--------------------------------------------------------------------------- Hinweise für Ex- und Import der DLL-Funktionen Exportieren: - Define MY_DLLNAME_EXPORT setzen (globale Compilereinstellung Importieren: statisch: - define MY_DLLNAME_STATIC_IMPORT setzen (globale Compilereinstellung) dynamisch: - define MY_DLLNAME_DYNAMIC_IMPORT_DECLARATION setzen (global). - cpp-File erstellen, welcher des Header wie folgt includiert: #define MY_DLLNAME_DYNAMIC_IMPORT_DEFINITION #include "dsConverterFunctions.h" //BEACHTE: dsConverterFunctions.h genau EIN einziges mal mit // dem Define MY_DLLNAME_DYNAMIC_IMPORT_DEFINITION // importieren BEACHTE: die Qualifiers verhalten sich im C++Builder und VisualC genau entgegengesetzt! Im C++Builder sind sie als mit __stdcall, in VC mit __cdecl zu importieren. Zu diesem Zweck das Define MY_DLLNAME_BDB oder MY_DLLNAME_VC setzen. Sind beide nicht gesetzt, wird standardmäßig __cdecl verwendet. ---------------------------------------------------------------------------*/ #ifndef mydllH #define mydllH //include-Wächter //--------------------------------------------------------------------------- //Compilerschalter für Import und Export #ifdef MY_DLLNAME_BCB #define MY_DLLNAME_QUALIFIER __stdcall #else #ifdef MY_DLLNAME_VC #define MY_DLLNAME_QUALIFIER __cdecl #else #define MY_DLLNAME_QUALIFIER __cdecl #endif #endif #ifdef MY_DLLNAME_EXPORT #define \ MY_DLLNAME_DLL_FUNCTION_DECLARATION( MY_DLLNAME_dll_qualifier, \ MY_DLLNAME_dll_returntype, \ MY_DLLNAME_dll_functionname) \ __declspec(dllexport) \ MY_DLLNAME_dll_returntype \ MY_DLLNAME_dll_qualifier \ MY_DLLNAME_dll_functionname #else #ifdef MY_DLLNAME_STATIC_IMPORT #define \ MY_DLLNAME_DLL_FUNCTION_DECLARATION( MY_DLLNAME_dll_qualifier, \ MY_DLLNAME_dll_returntype, \ MY_DLLNAME_dll_functionname) \ __declspec(dllexport) \ MY_DLLNAME_dll_returntype \ MY_DLLNAME_dll_qualifier \ MY_DLLNAME_dll_functionname #else #ifdef MY_DLLNAME_DYNAMIC_IMPORT_DEFINITION #ifndef MY_DLLNAME_DYNAMIC_IMPORT_DEFINITION_FUN_PTR #define \ MY_DLLNAME_DLL_FUNCTION_DECLARATION( MY_DLLNAME_dll_qualifier, \ MY_DLLNAME_dll_returntype, \ MY_DLLNAME_dll_functionname) \ \ \ MY_DLLNAME_dll_returntype \ MY_DLLNAME_dll_qualifier \ (*MY_DLLNAME_dll_functionname) #else #undef MY_DLLNAME_DLL_FUNCTION_DECLARATION #define \ MY_DLLNAME_DLL_FUNCTION_DECLARATION( MY_DLLNAME_dll_qualifier, \ MY_DLLNAME_dll_returntype, \ MY_DLLNAME_dll_functionname) \ \ typedef \ MY_DLLNAME_dll_returntype \ MY_DLLNAME_dll_qualifier \ (*MY_DLLNAME_dll_functionname) #endif #else #ifdef MY_DLLNAME_DYNAMIC_IMPORT_DECLARATION #define \ MY_DLLNAME_DLL_FUNCTION_DECLARATION( MY_DLLNAME_dll_qualifier, \ MY_DLLNAME_dll_returntype, \ MY_DLLNAME_dll_functionname) \ \ extern \ MY_DLLNAME_dll_returntype \ MY_DLLNAME_dll_qualifier \ (*MY_DLLNAME_dll_functionname) #else #error zum Einbinden des Headers müssen folgende defines gesetzt sein : \ MY_DLLNAME_EXPORT Exportieren der Funktionen \ (für das Compilieren der DLL) \ MY_DLLNAME_STATIC_IMPORT Für das statische Importieren der DLL \ MY_DLLNAME_DYNAMIC_IMPORT_DEFIONITION Genau einmal in einem Projekt, in \ welchem die DLL dynamisch geladen \ werden soll. Der Aufruf von dsLoadDLL \ importiert die Funktionen (in \ Kombination mit \ MY_DLLNAME_DYNAMIC_IMPORT_DECLARATION). \ MY_DLLNAME_DYNAMIC_IMPORT_DECLARATION Funktionsdeklaration in einem Projekt \ in dem die DLL dynamisch geladen wurde #endif #endif #endif #endif //Compilerschalter für Import und Export //--------------------------------------------------------------------------- //Deklaration der Funktionen extern "C" { /** Beispiel für eine Funktion */ DAYSECONDS_DLL_FUNCTION_DECLARATION ( DAYSECONDS_QUALIFIER, //Qualifizierer int, //Rückgabewert foo)( const long bar); //Funktionsname und Parameter } //Deklaration der Funktionen //---------------------------------------------- //dynamische Importieren der Funktionen #ifdef MY_DLLNAME_DYNAMIC_IMPORT_DEFINITION #include "windows.h" #ifdef MY_DLLNAME_LOAD_FUN #error Header "mydll.h" bei gesetztem define \ MY_DLLNAME_DYNAMIC_IMPORT_DEFINITION nur EINMAL pro Projekt einbinden #endif #ifndef MY_DLLNAME_DYNAMIC_IMPORT_DECLARATION #error Bei gesetztem MY_DLLNAME_DYNAMIC_IMPORT_DEFINITION auch das \ define MY_DLLNAME_DYNAMIC_IMPORT_DECLARATION setzen #endif #ifndef MY_DLLNAME_DYNAMIC_IMPORT_DEFINITION_FUN_PTR #define MY_DLLNAMEDYNAMIC_IMPORT_DEFINITION_FUN_PTR #define FOO namespace //unnamed { namespace MY_DLLNAME_funptr //über den Namensraum wird der Funktionszeiger-Typ von der { //Funktionszeiger-Variable unterschieden #undef mydllH //include-Wächter ausschalten #include "dsConverterFunctions.h" //Funktions-ptr-Type-Deklaration #define mydllH } } #undef MY_DLLNAMEDYNAMIC_IMPORT_DEFINITION_FUN_PTR #endif #ifndef MY_DLLNAME_DYNAMIC_IMPORT_DEFINITION_FUN_PTR #define MY_DLLNAME_LOAD_FUN( FUN_PTR_NAME, \ FUN_NAME_ASSTRING) \ FUN_PTR_NAME = MY_DLLNAME_funptr::FUN_PTR_NAME(GetProcAddress( dll, FUN_NAME_ASSTRING)); \ if(!FUN_PTR_NAME) reportError( FUN_NAME_ASSTRING); /** Lädt die Funktionen der DLL dynamisch. Liefert 1 als Rückgabewert, wenn die DLL nicht gefunden wurde, sonst 0. @param reportError Diese Funktion wird aufgerufen, wenn die geladene DLL eine Funktion nicht unterstützt. Übergeben wird der Name der Funktion */ int dsLoadDll( void(*reportError)( const char*) ) { assert( NULL != reportError); HANDLE dll( (LoadLibrary("dayseconds.dll"))); if(!dll) return 1; //Code zum Laden der Funktionen DAYSECONDS_LOAD_FUN( foo, "_foo"); return 0; } #endif #endif #endif //include-WächterZugehöriger Export (DLL-Seite)
//MY_DLLNAME_EXPORT muss gesetzt sein #include "myDll" extern "C" { DAYSECONDS_DLL_FUNCTION_DECLARATION ( DAYSECONDS_QUALIFIER, int, foo)( const long bar) { //whatever return 0; } }zugehöriger dynamischer Import (Client-Seite)
#include <iostream> //MY_DLLNAME_DYNAMIC_IMPORT_DECLARATION muss gesetzt sein #define MY_DLLNAME_DYNAMIC_IMPORT_DEFINITION #include "myDll.h" //BEACHTE: myDll.h genau EIN einziges mal mit // dem Define MY_DLLNAME_DYNAMIC_IMPORT_DEFINITION // importieren namespace client { void notLoadable( const char* msg) { std::cerr << "Funktion '"<<msg<<"' konnte nicht aus der daySeconds.dll geladen werden.\n"<<; }; /** Lädt die dll "MyDLL" dynamisch.*/ void loadMyDll() { static bool loaded(false); //es wird nur einmal geladen if(!loaded) { if (dsLoadDll( notLoadable)) { std::cerr << "daySeconds.dll konnte nicht geladen werden"; } } } void doSomething() { //... int foosValue( foo(13)); //Aufruf der DLL-Funktion } } //clent
-
kartoffelsack schrieb:
Hier mal ein ungefragter Vorschlag,
Dann sag ich mal, ebenfalls ungefragt, daß VC User selbstverständlich ebenfalls __stdcall ex- und importieren sollen und nicht __cdecl. Und die, die noch etwas anderes benutzen, sollen auch __stdcall verwenden.