代码之家  ›  专栏  ›  技术社区  ›  Adam Haile

从DLL导出C++类

  •  24
  • Adam Haile  · 技术社区  · 16 年前

    我的C/C++开发的大部分都涉及模块化的模块文件,绝对没有任何类,所以通常当我需要做一个 动态链接库 使用可访问的功能,我只是使用标准导出它们 __declspec(dllexport) 指令。然后通过动态访问它们 LoadLibrary() 或者在编译时使用头文件和lib文件。

    当您想导出整个类(以及所有的公共方法和属性)时,如何执行此操作?

    是否可以在运行时动态加载该类?如果可以,如何加载?

    对于编译时链接,您如何处理头和lib?

    6 回复  |  直到 10 年前
        1
  •  15
  •   user2189331    16 年前

    晚装怎么样?与装载一样 它与loadLibrary()和 getProcAddress()?我已经习惯了 在运行时加载库 如果你能做到那就太好了 在这里。

    所以有两种方法可以加载DLL。第一种方法是引用dll中的一个或多个符号(例如,类名),提供适当的import.lib并让链接器解决所有问题。

    第二种方法是通过LoadLibrary显式加载DLL。

    这两种方法都适用于C级函数导出。您可以让链接器处理它,也可以如您所指出的那样调用getprocaddress。

    但说到出口 通常只使用第一种方法,即隐式链接到DLL。在这种情况下,DLL是在应用程序启动时加载的,如果找不到DLL,应用程序将无法加载。

    如果要链接到在dll中定义的类,并且希望在程序启动后某个时间动态加载该dll,则有两个选项:

    1. 使用一个特殊的工厂函数创建类的对象,该函数在内部必须使用(一点点)汇编程序将新创建的对象“连接”到其适当的偏移量。显然,这必须在加载dll之后的运行时完成。对这种方法有一个很好的解释 here .

    2. 使用A delay-load DLL .

    所有的事情都考虑到了…最好是使用隐式链接,在这种情况下,您肯定希望使用上面所示的预处理器技术。实际上,如果您在Visual Studio中创建一个新的dll并选择“导出符号”选项,这些宏将为您创建。

    祝你好运。。。

        2
  •  16
  •   Graeme Perrow    16 年前

    当您构建动态链接库和将使用动态链接库的模块时,您可以使用某种定义来区分两者,然后在类头文件中执行如下操作:

    #if defined( BUILD_DLL )
        #define IMPORT_EXPORT __declspec(dllexport)
    #else
        #define IMPORT_EXPORT __declspec(dllimport)
    #endif
    class IMPORT_EXPORT MyClass {
        ...
    };
    

    编辑:crashmstr打败了我!

        3
  •  12
  •   crashmstr    16 年前

    我使用一些宏来标记导入或导出代码

    #ifdef ISDLL
    #define DLL __declspec(dllexport)
    #endif
    
    #ifdef USEDLL
    #define DLL __declspec(dllimport)
    #endif
    

    然后在头文件中声明类:

    class DLL MyClassToExport { ... }
    

    然后 #define ISDLL 在诽谤案中,以及 USEDLL 在将头文件包含在要使用类的位置之前。

    我不知道你是否需要做任何不同的工作 LoadLibrary

        4
  •  12
  •   SridharKritha    10 年前

    从DLL导出C++类的简单工作示例:

    下面给出的示例仅为您提供了一个简短的概述,说明了dll和exe如何相互作用(不言而喻),但要将其更改为生产代码,还需要添加更多内容。

    全样本示例分为两部分

    a.创建.dll库(mydll.dll)

    b.创建使用.dll库(应用程序)的应用程序。

    a..dll项目文件(mydll.dll):

    1。DLL报头

    #ifdef  MYDLL_EXPORTS 
    #define DLLCALL __declspec(dllexport)   /* Should be enabled before compiling 
                                               .dll project for creating .dll*/
    #else
    #define DLLCALL __declspec(dllimport)  /* Should be enabled in Application side
                                              for using already created .dll*/
    #endif
    
    // Interface Class
    class ImyMath {
    public:
        virtual ~ImyMath() {;}
        virtual int Add(int a, int b) = 0;
        virtual int Subtract(int a, int b) = 0;
    };
    
    // Concrete Class
    class MyMath: public ImyMath {
    public:
        MyMath() {}
        int Add(int a, int b);
        int Subtract(int a, int b);
        int a,b;
    };
    
    //  Factory function that will return the new object instance. (Only function
    //  should be declared with DLLCALL)
    extern "C" /*Important for avoiding Name decoration*/
    {
        DLLCALL ImyMath* _cdecl CreateMathObject();
    };
    
    // Function Pointer Declaration of CreateMathObject() [Entry Point Function]
    typedef ImyMath* (*CREATE_MATH) ();
    

    2。DLLSRCCPP

    #include "dllHeader.h"
    
    // Create Object
    DLLCALL ImyMath* _cdecl CreateMathObject() {
        return new MyMath();
    }
    
    int MyMath::Add(int a, int b) {
        return a+b;
    }
    
    int MyMath::Subtract(int a, int b) {
        return a-b;
    }
    

    b.加载并链接已创建的.dll文件的应用程序项目:

     #include <iostream>
    #include <windows.h>
    #include "dllHeader.h"
    
    int main()
    {
        HINSTANCE hDLL = LoadLibrary(L"MyDLL.dll"); // L".\Debug\MyDLL.dll"
    
        if (hDLL == NULL) {
            std::cout << "Failed to load library.\n";
        }
        else {
            CREATE_MATH pEntryFunction = (CREATE_MATH)GetProcAddress(hDLL,"CreateMathObject");
            ImyMath* pMath = pEntryFunction();
            if (pMath) {
                std::cout << "10+10=" << pMath->Add(10, 10) << std::endl;
                std::cout << "50-10=" << pMath->Subtract(50, 10) << std::endl;
            }
            FreeLibrary(hDLL);
        }
        std::cin.get();
        return 0;
    }
    
        5
  •  7
  •   Eli Bendersky    13 年前

    最近我问自己同样的问题,并总结了我的发现。 in a blog post . 你会发现它很有用。

    它包括从DLL导出C++类,以及动态加载它们。 LoadLibrary 并讨论了其中的一些问题,如内存管理、名称管理和调用约定。

        6
  •  0
  •   Tim Cooper    12 年前

    如果您愿意将vtable放在要导出的类中,可以导出返回接口的函数,并在.dll中实现该类,然后将其放在.def文件中。你可能需要做一些申报的小把戏,但不应该太难。

    就像com一样。:)