我大部分的C/C++开发包括单片模块文件,绝对没有任何类,所以通常当我需要做一个DLL与使用的功能我只是使用标准的导出它们__declspec(dllexport)
指令.然后通过LoadLibrary()
头文件和lib文件动态地或在编译时访问它们.
如果要导出整个类(及其所有公共方法和属性),如何执行此操作?
是否可以在运行时动态加载该类,如果是,如何?
如何使用头和lib进行编译时链接?
当您构建DLL和将使用DLL的模块时,可以使用某种#define来区分其中一个,然后您可以在类头文件中执行以下操作:
#if defined( BUILD_DLL ) #define IMPORT_EXPORT __declspec(dllexport) #else #define IMPORT_EXPORT __declspec(dllimport) #endif class IMPORT_EXPORT MyClass { ... };
编辑:crashmstr打败了我!
后期绑定怎么样?在使用LoadLibrary()和GetProcAddress()加载它时?我习惯于在运行时加载库,如果你能在这里做到这一点会很棒.
因此有两种方法可以加载DLL.第一种是引用DLL中的一个或多个符号(例如,您的类名),提供适当的导入.LIB并让链接器解决所有问题.
第二种是通过LoadLibrary显式加载DLL.
这两种方法都适用于C级函数导出.您可以让链接器处理它,也可以按照您的说明调用GetProcAddress.
但是当涉及到导出的类时,通常只使用第一种方法,即隐式链接到DLL.在这种情况下,DLL在应用程序启动时加载,如果找不到DLL,则无法加载应用程序.
如果要链接到DLL中定义的类,并且希望在程序启动后的某个时间动态加载该DLL,则有两个选项:
使用特殊的工厂函数创建类的对象,该函数在内部将必须使用(一小部分)汇编程序将新创建的对象"挂钩"到其适当的偏移量.这显然必须在DLL加载后的运行时完成.这里可以找到这种方法的一个很好的解释.
使用延迟加载DLL.
考虑所有事情......可能更好的方法是使用隐式链接,在这种情况下,您肯定希望使用上面显示的预处理器技术.实际上,如果在Visual Studio中创建新DLL并选择"导出符号"选项,则会为您创建这些宏.
祝好运...
我使用一些宏来标记导入或导出的代码
#ifdef ISDLL #define DLL __declspec(dllexport) #endif #ifdef USEDLL #define DLL __declspec(dllimport) #endif
然后在头文件中声明该类:
class DLL MyClassToExport { ... }
然后#define ISDLL
在libary中,USEDLL
在将头文件包含在要使用该类的位置之前.
我不知道你是否可能需要做任何不同的工作 LoadLibrary
添加一个简单的工作示例,用于从DLL导出C++类:
下面给出的示例仅为您提供了dll和exe如何相互交互的简短概述(自解释),但需要添加更多内容才能更改为生产代码.
完整的示例示例分为两部分
A.创建.dll库(MyDLL.dll)
B.创建使用.dll库(应用程序)的应用程序.
A. .ll项目文件(MyDLL.dll):
1. dllHeader.h
#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. dllSrc.cpp
#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#include #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; }
最近我问自己完全相同的问题,并在博客文章中总结了我的发现.你可能会发现它很有用.
它包括从DLL导出C++类,以及动态加载它们LoadLibrary
,并讨论其中的一些问题,如内存管理,名称修改和调用约定.