
在编写C ++程序时,通常需要将类编写为DLL,以便客户端程序调用. 这样的DLL可以导出整个类或该类的方法.
一个,导出整个课程
该方法非常简单,您只需要在类头文件中的类和类名之间以及同时提供给客户端调用程序的另一个类头文件中添加_declspec(dllexport). 在名称之间添加_declspec(dllimport). 为了允许客户端程序和DLL程序共享此类的头文件,通常在类头文件中使用宏和预编译指令. 下面的DLLTest.h:
#ifdef DLL_TEST_API #else #define DLL_TEST_API _declspec(dllimport) #endif Class DLL_TEST_API CDLLTest { Public: CDLLTest(); ~CDLLTest(); int Add(int a, int b); };
DLLTest.cpp如下:
#define DLL_TEST_API _declspec(dllexport) #include “DLLTest.h” ………………………………………

通过这种方式,在编译DLL时,DLL_TEST_API被定义为_declspec(dllexport),而在编译客户端程序时,其被定义为_declspec(dllimport).
第二,导出此类的一种或几种方法.
这时,您需要在成员函数名称(例如DLLTest.h)之前放置_declspec(dllexport):
#ifdef DLL_TEST_API #else #define DLL_TEST_API _declspec(dllimport) #endif Class CDLLTest { Public: CDLLTest(); ~CDLLTest(); int DLL_TEST_API Add(int a, int b); };
但是,如果仅是这种情况,则在客户端程序#includes此头文件之后,在定义DLLTest类的对象(静态链接DLL)之后,客户端程序将无法链接通过,并提示构造函数和分析无法解析构造函数. 在这种情况下,您需要在构造函数和析构函数之前添加DLL_TEST_API宏.
当然这里有问题. 导出类的功能后,名称将更改. 我们可以在函数名称前添加extern“ C”,例如extern“ C” DLL_TEST_API int Add(int a,int b);但这只能解决调用C和C ++时的名称更改问题. 可靠的方法是添加一个模块定义文件def,在该文件中定义导出函数的名称,我们将在后面看到示例.

在编写DLL之后,只有客户端程序才能调用DLL,它是静态调用的,而DLL是动态调用的.
首先怎么写dll文件,静态调用DLL
此方法很简单,将DLLTest.h头文件和DLLTest.lib,DLLTest.dll文件复制到客户端程序的当前目录中,在客户端程序中#include
然后,您可以像使用本地类一样在客户端程序中使用DLL,例如:
CDLLTest dllTest; dllTest.Add(1,2);
第二怎么写dll文件,动态调用DLL

动态调用此DLL,您需要修改此类.
首先,在DLLTest.cpp文件中添加一个全局函数,该函数可以返回此类的实例. 这样,在客户端程序调用此全局函数并获取该类的实例之后,您可以调用Method类的实例.
extern “C” _declspec(dllexport) CDLLTest* GetInstance() { return new CDLLTest; }
注意: extern“ C”仅解决C和C ++编译器之间的兼容性问题. 如果需要与其他编译器兼容,一种可靠的方法是添加.def文件. 该文件的内容如下:
LIBRARY “DLLTest”
EXPORTS
GetInstance = GetInstance
通过这种方式,指定的DLL函数的名称保持不变.

通过这种方式,客户端程序可以通过该函数获得该类的实例. 如下:
首先需要定义一个函数指针类型:
typedef CDllTestBase* (*pfGetInst)(); //注:CDllTestBase类后面会介绍。 HMOUDLE hMod = LoadLibrary( _T(“DLLTest.DLL”) ); if(hMod) { pfGetInst pfGetInstance = (pfGetInst)GetProcAddress(“GetInstance”); if( p ) { //通过基类指针指向派生类对象 CDllTestBase * pInst = pfGetInstance ();
if( NULL != pInst )
{ pInst->Add( 1,2);
} if( NULL != pInst ) { //释放对象 delete pInst;
} }
}
当然,您仍然需要包括DLL头文件DLLTestBase.h. 如果将先前编写的头文件DLLTest.h直接复制到客户端程序的当前目录并包含它,则在编译和连接时无法传递,我们需要修改此头文件,首先添加一个.h文件DLLTestBase .h,在此文件中,我们将需要在客户端程序中调用的函数称为纯虚函数,然后让CDLLTest类从CDLLTestBase类DLLTestBase.h继承如下:
Class CDLLTestBase { Public: Virtual ~CDLLTestBase(){};//虚析构函数,且为内联函数 Virtual int Add(int a, int b) = 0; }
修改后的DLLTest.h如下:
#include “DLLTestBase.h” Class CDLLTest : public CDLLTestBase { Public: CDLLTest(); ~CDLLTest(); int Add(int a, int b); };
注意: 这里的DLLTestBase需要提供一个虚拟的析构函数,以便客户端类可以通过基类指针释放派生的类对象.
通过这种方式,您只需要将DLLTestBase.h复制到客户端程序的当前目录,然后在客户端程序中#include“ DLLTestBase.h”,就可以如上所述在客户端程序中调用DLL. 方法.
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-171794-1.html
给它留个记性免得在来同时也当军演了练练手