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 FAQ

    Header (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ächter
    

    Zugehö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.


Anmelden zum Antworten