刚到公司,发了一个本子一支笔一个文件夹(VC++深入详解、C++ Primer、Effective C++、Effective STL)。
废话不多说,第一项任务:熟悉VS,联系创建dll文件,并从中导出函数供应用程序使用。
一、简介一下dll
DLL(Dynamic Linkable Library),动态链接库,可以向程序提供一些函数、变量或类。通常不能直接运行,也不能接收消息。它们是一些独立的文件,只有当其他模块调用dll中的函数时,才发挥作用。
Windows API 中所有的函数都包含在dll中,有三个最重要的:
1、Kernel32.dll:包含用于管理内存、进程和线程的函数。
2、User32.dll:包含用于执行用户界面任务的函数。
3、GDI32.dll:包含哪些用于画图和显示文本的函数。
【静态库】
函数和数据被编译进一个二进制文件(.lib)。编译连接时,复制这些函数和数据,把它们和应用程序的其它模块组合起来,创建最终的可执行文件(.exe)。发布产品时只需发布可执行文件,不需要发布静态库。
【动态库】
动态库往往提供两个文件:
引入库文件(.lib)——包含导出的函数和变量的符号名。
DLL文件(.dll)——包含该DLL实际的函数和数据。
编译链接时不复制,运行时才加载(将DLL映射到进程的地址空间中),然后访问导出函数。发布产品时除了可执行文件,还要有动态链接库。
二、从dll中导出函数(采用隐式加载dll)
1、新建一个dll,在dll.cpp中写两个简单的函数:
int add(int a, int b)
{ return a + b;
}
int subtract(int a,int b)
{ return a = b;
}
点击生成dll,则会在debug目录下产生11个文件,其中包含.lib和.dll文件。
2、在想要导出的函数前,加上导出标志符:_declspec(dllexport)。如下:
_declspec(dllexport) int add(int a,int b) { return a+b; } _declspec(dllexport)int subtract(int a,int b) { return a-b; }
3、创建一个基于对话框的应用程序test.exe。
//在testDlg.cpp中声明函数 extern int add(int a,int b); extern int subtract(int a,int b);
//接着实现两个按钮的消息映射函数
void CtestDlg::OnBnClickedBtnAdd() { OnBtnAdd();//手动添加 }
void CtestDlg::OnBnClickedBtnSubtract() { OnBtnSubtract();//手动添加 }
void CtestDlg::OnBtnAdd(void) { CString str; str.Format("5 + 3 = %d",add(5,3)); MessageBox(str);
}
void CtestDlg::OnBtnSubtract(void) { CString str; str.Format("5 - 3 = %d",subtract(5,3)); MessageBox(str);
} 4、编译一下,出现三个错!没有载入dll......
将刚才生成的.lib和.dll两个文件复制到test所在目录下。
编译还是错!没有设置库......
在项目--属性--链接器--输入--附加依赖项--填写“dll.lib”
再次生成exe就好啦!
三、从dll中到处类(采用隐式加载dll)
先注明一点:不是导出就一定能够使用该类,仍旧受限于类本身的访问权限!
1、在dll.h中写一个类,并添加导出标志符: class _declspec(dllexport) Point { public: void output(int x,int y); }; 在dll.cpp中实现:
void Point::output(int x,int y) { //返回调用者进程当前正在使用的那个窗口的句柄 HWND hwnd = ::GetForegroundWindow(); //获取DC HDC hdc = ::GetDC(hwnd); char buf[20]; memset(buf,0,20); sprintf(buf,"x = %d,y = %d",x,y); //输出坐标 ::TextOut(hdc,0,0,buf,strlen(buf)); //释放DC ::ReleaseDC(hwnd,hdc);
} 因为用到库函数,所以在dll.cpp中包含头文件:
#include "Windows.h" #include "stdio.h" 2、在test.cpp中使用这个类:
void CtestDlg::OnBtnOutput(void) { Point pt; pt.output(5,3);
}
当然,也要包含定义类的头文件:
#include "dll.h" 3、将.lib和.h文件放在test目录下,将.dll文件放在test\debug目录下。
4、编译生成exe,完成。
【使用宏定义】
1、在dll.h文件中添加一个宏:
#ifdef AAAA
#define DLL_API _declspec(dllexport)
#else
#define DLL_API _declspec(dllimport)
#endif
则定义类如下:
class DLL_API Point { public: void output(int x,int y); };
2、在stdafx.h中:#define AAAA
(dll.cpp包含了stdafx.h所以就是export啦!testDlg.cpp中没有定义,所以就是impoort!)
参考资料:VC++深入详解——孙鑫