// 第一种方法
//只需要在导出类加上_declspec(dllexport),就可以实现导出。对象空间还是在使用者的模块,dll只提供类中的函数代码,调用者导入库后, //声明该类的对象,即可调用类中函数 class _declspec(dllexport) CDerived { public: CDerived(); ~CDerived(); public: int InitVideo(); int Play(); private: int VideoState; };
//第二种 //这种方式是比较合适的,跟com类似。 //结构是这样的:导出类是一个派生类,派生自一个抽象类,类中都是纯虚函数。使用者需要知道这个抽象类的结构。 //DLL最少只需要提供一个用于获取抽象类对象指针的接口。使用者跟DLL提供者共用一个抽象类的头文件,使用者依赖于DLL的东西很少, //只需要知道抽象类的接口,以及获取对象指针的导出函数,对象内存空间的申请是在DLL模块中做的,释放也在DLL模块中完成,最后记得要调用释放对象的函数。 //这种方式比较好,通用,产生的DLL没有特定环境限制。借助了C++类的虚函数。一般都是采用这种方式。除了对DLL导出类有好处外,采用接口跟实现分离, //可以使得工程的结构更清晰,使用者只需要知道接口,而不需要知道实现。 //部分代码:
<pre name="code" class="cpp">//抽象类 class CBase { public: virtual int InitVideo() =0; virtual int Play() =0; virtual void Release() =0; }; __declspec( dllexport ) CBase *GetBaseInstance();
//派生类 #include "Base.h" class CDerived:public CBase { public: CDerived(); ~CDerived(); public: int InitVideo(); int Play(); void Release(); private: int VideoState; };
//派生类简单实现 #include "Derived.h" __declspec( dllexport ) CBase *GetBaseInstance() { return new CDerived; } CDerived::CDerived() { VideoState=-1; } CDerived::~CDerived() { } int CDerived::InitVideo() { return 1; } int CDerived::Play() { return 2; } void CDerived::Release() { delete this;<span style="font-family: Arial, Helvetica, sans-serif;">}</span>
//调用者引入导出库后,加入Base.h //调用 CBase * m_pBase=GetBaseInstance(); re=m_pBase->InitVideo();//DLL导出时 名字改变的问题 C++编译器在生成DLL时,会对导出函数进行改编,并且不同的编译器使用的改编规则不同。此时如果调用放使用C语言的话,就会出现问题。解决方法:在导出函数时,需要加上限定符 extern "C".即: extern "C" _declspec(dllexport)_stdcall是C调用约定,标准调用约定是WINAPI调用约定,