第一步,新建项目,选择win32项目(不是win32控制台程序),命名为ClassDll根据导向选择DLL,完成。
示例图1-1
第二步,新建一个头文件,命名为 ClassDll.h,在这个头文件里添加下面的代码:
class _declspec(dllexport) Point
{
public:
void output(int x,int y);
int Add(int a,int b);
};
注意:此处的 _declspec(dllexport)是标识符,用于标识导出的类Point
第三步,新建一个用于Point类的定义的文件,命名为ClassDll.cpp,这个文件包含的全部代码如下:
#include "stdafx.h" #include "ClassDll.h" #include <Windows.h> #include <stdio.h> #include <tchar.h> void Point::output(int a ,int b) { //返回调用者进程当前正在使用的那个窗口的句柄 HWND hwnd=GetForegroundWindow(); //获取DC HDC hdc=GetDC(hwnd); char buf[20]; memset(buf,0,20); sprintf(buf,"x=%d,y=%d",a,b); //输出坐标 TextOut(hdc,0,0,buf,strlen(buf)); //释放DC ReleaseDC(hwnd,hdc); } int Point::Add(int a,int b) { return a+b; } //用于外部主程序调用类的方法 extern "C" _declspec(dllexport) void show(int a,int b) { Point pt; pt.output(a,b); //MessageBox(_T("测试成功!")); } //用于外部主程序调用类的方法 extern "C" _declspec(dllexport) int Add(int a,int b) { return a+b; }
第四步,到现在为止,我们已经实现了Point这个类,包含了两个方法,注意:这两个方法的参数和返回值。现在需要在新的工程中引用这个Dll文件。新建一个MFC对话框程序,工程命名为DllTest,在界面中添加一个按钮,并在此按钮中添加引用Dll的测试代码。
示意图4-1
第五步,将每次更新动态链接库Debug文件中的ClassDll.dll,ClassDll.lib拷贝到主程序的根目录下。示意图如下:
注意:(动态加载动态链接库:不需要将生成动态链接库文件中的头文件加载到调用程序中,同时也不需要将.lib文件复制到调用文件的根目录下。只需要将.dll复制到调用文件的根目录下即可)
第六步,程序调用(因为动态链接库中Add函数前加入extern "C"(如上标红的代码)因此名字导出时不发生名字改编也就是不会变成?Add@@YAXHH@Z(参考Doc使用dumpbin导入数据……文档),所以在调用程序中GetProcAddress函数的参数直接写为Add(如果动态链接库中Add函数发生名字改编则调用程序中GetProcAddress参数为?Add@@YAXHH@Z))(show函数同理)
测试代码(在界面中的一个按钮消息响应函数中实现)
void CDllTestDlg::OnBtnTest()
{
HINSTANCE hInst; //定义一个实例句柄对象
hInst=LoadLibrary(_T("ClassDll.dll")); //动态加载Dll
typedef void (*ADDPROC1)(int a,int b); //定义函数指针类型
ADDPROC1 Output=(ADDPROC1)GetProcAddress(hInst,"show");//调用dll类中的方法
if(!Output)
{
MessageBox(_T("获取函数地址失败"));
return;
}
Output( 90, 9);
typedef int (*ADDPROC)(int a,int b); //定义函数指针类型
ADDPROC Add=(ADDPROC)GetProcAddress(hInst,"Add");//调用dll类中的方法
if (!Add)
{
MessageBox(_T("获取函数地址失败"));
return;
}
CString str;
str.Format(_T("%d"),Add(2,4));
MessageBox(str);
}
第七步,程序执行结果:
图7-1 程序引用dll测试结果