标签: 转载 |
初学vc就要自己封装动态库,我是用c写的程序代码,在网上找了半天,发现vc++深入详解(孙鑫)的书不错,对于第十九章中的动态链接库,讲的很详细,学习了很多。
我的动态链接库的制作,总结了一下,从小的简单的dll逐渐逐层放大,记录下来,以后方便查找。
1.Win32 DLL的创建和使用
首先利用vc++新建一个Win32Dynamic-Link Library 类的工程,工程取名为:Dll1,并在AppWizard的第一步选择“An empty Dll project”选项,即创建一个空的动态链接库工程。然后,为该工程添加一个c++源文件Dll1.cpp,向其中添加函数,分别为:加法运算和减法运算函数,代码为:
int add(int a,int b)
{return a+b;}
int subtract(int a,int b)
{return a-b;}
点击bulid命令可生成动态链接库,名字为Dll1.dll文件。
生成DLL后,就可以导出函数,但是需要在每一个将要被导出的函数前面添加标识符_declspec(dllexport),所以修改上述代码如下:
_declspec(dllexport) int add(int a,int b)
{return a+b;}
_declspec(dllexport) int subtract(int a,int b)
{return a-b;}
然后点击bulid命令,下面的窗口会输出如下信息:
——————Configuration:Dll1-Win32 Debug-------------——
Compiling...
Dll1.cpp
Linking ...
Creating library Debug/Dll1.lib and object Debug/dll1.exp
Dll1.dll -0 error(s),0 wrning(s)
可以看到,生成两个新文件,其中Dll1.lib 文件就是前面提到的引入库文件,该文件保存的是Dll1.dll中导出的函数和变量的符号名:Dll1.exp文件是一个输出库文件,在这里,该文件并不重要。
因为C++支持函数重载,对于从在的多个函数来说,其函数名都是一样的,为了加以区分,在编译连接时,c++会按照自己的规则篡改函数的名称,称为“名字改编”,
2。隐式链接方式加载DLL
编写一个测试程序测试这个动态库,新建一个.cpp文件取名为dlltest.cpp。
(1)利用extern声明外部函数
为了让编译器知道这两个函数,需要对函数做一个声明,即在函数名前面加上extern 表示函数是在外部定义的。如下:
extern int add(int a,int b);
extern int subtract(int a,int b);
int main()
{
printf("%d",add(5,3));
printf("%d",subtract(6,4));
}
点击bulid命令,会出现三个错误:
linking...
error executing link.exe
可看出,编译成功,因为add和subtract函数做了声明,但在程序连接时出错,因为连接器没有找到该信息,
为了解决这个问题,需要利用动态链接库的引入库文件,将Dll1..lib 复制到dlltest.cpp目录下,然后再dlltest.cpp程序中,选择【工程-设置-连接选项卡】在"Object/library modules"添加dll1.lib再次运行,就会成功。
(2)利用_declspc(dllimport)声明外部函数
如:_declspec(dllimport) int add(int a,int b);
_declspec(dllimport) int subtract(int a,int b);
与使用extern关键字这种方式相比,使用_declspec(dllimport)标识符声明外部函数时,他将告诉编译器该函数是从动态链接库中引入的,编译器可以生成运行效率更高的代码,因此,如果调用的函数来自于动态链接库,因该采用这种方式声明外部函数。
3。完善W32Dll例子
要想将生成的Dll提供给用户,通常在编写动态链接库时,都会提供一个头文件,在此头文件中提供Dll导出函数原型的声明,以及函数的有关注释文档。
为Dll1工程添加一个头文件:Dll1.h 添加代码如下:
_declspec (dllimport) int add(int a,int b);
_declspec(dllimport) int subtract(int a,int b);
然后在测试文件中添加#include"路径/Dll1.h"