通常的DLL导出类方法,一个简单的例子:java
dllExample.h:安全
1 #pragma once 2 3 #ifdef DLL_EXPORTS 4 #define DLL_API __declspec(dllexport) 5 #else 6 #define DLL_API __declspec(dllimport) 7 #endif 8 9 class DLL_API ExportClass 10 { 11 pirvate: 12 int x; 13 public: 14 void foo(); 15 };
dllExample.cpp:函数
1 #define DLL_EXPORTS 2 #include "dllExample.h" 3 4 void ExportClass::foo() 5 { 6 //do something... 7 return; 8 }
而外部代码只须要包含头文件,就会自动导入ExportClass的定义。
编译时链接该DLL对应的lib,运行时提供DLL文件,便可正常运行。spa
不过这种简单的DLL导出存在一个限制,若是咱们导出的类中含有非C++基础类型:指针
dllExample.h:code
1 #pragma once 2 3 #ifdef DLL_EXPORTS 4 #define DLL_API __declspec(dllexport) 5 #else 6 #define DLL_API __declspec(dllimport) 7 #endif 8 9 class DLL_API ExportClass 10 { 11 pirvate: 12 std::string x; //此处的string类型导出是不安全的 13 public: 14 void foo(); 15 };
咱们知道, 对于STL,微软为每一个版本的VS都有不一样的实现,VS2008(VC90),VS2010(VC100),VS2013(VC120)。
因为不一样的STL的实现,咱们不能在不一样的版本见直接传递std::string, 不然运行期可能出现不可预知的错误。
而事实上咱们在ExportClass中的std::string x变量是不但愿被外部直接使用的,也就是并无export的必要,事实上,不建议让dll向外导出任何关于非C++基础类型的定义。
可是因为ExportClass须要向外导出(由于须要使用foo()函数),应该如何处理这样的矛盾呢?blog
对于这样的问题,咱们须要使用C++的抽象类(其实就是java中的interface概念)来解决:
咱们须要:
1. 申明一个只有纯虚函数和C++基础类型的基类,全部须要向外部导出的定义都包含在该类中。
2. 申明另外一个类,继承该基类。
3. 实现一个返回基类函数指针的getInstance函数,即返回一个派生类实例的工厂方法。
4. 在外部代码中,经过多态机制访问该类。继承
dllExample.h:get
1 #pragma once 2 3 #ifdef DLL_EXPORTS 4 #define DLL_API __declspec(dllexport) 5 #else 6 #define DLL_API __declspec(dllimport) 7 #endif 8 9 class DLL_API ExportInterface 10 { 11 public: 12 virtual void foo() = 0; 13 }; 14 15 extern "C" DLL_API ExportInterface* getInstance(); 16 17 #ifdef DLL_EXPORTS //咱们并不须要向外导出该类的定义,在外部代码编译时,也不须要包含此类的定义。 18 class ExportClass: public ExportInterface 19 { 20 pirvate: 21 std::string x; //因为外部代码对此不可见,此处的std::string是安全的。 22 public: 23 void foo(); //函数体在dllExample.cpp中实现 24 }; 25 #endif
dllExample.cpp:string
#define DLL_EXPORTS #include "dllExample.h" extern "C" DLL_API ExportInterface* getInstance() { ExportInterface* pInstance = new ExportClass(); return pInstance; } void ExportClass::foo() { //do something... return; }