本文以Visual Studio 2010为例,介绍在该环境中将一个普通C函数封装成一个dll,同时生成dll对应的lib索引文件的过程。
在VS 2010中启动向导,如下图:
假定项目名为 dll_test,当向导进行到“应用程序设置”这一步,设置的内容如下:
点击“完成”按钮。接下来在解决方案中添加两个文件dll_test.h和dll_test.c,如下图:
其中示例程序头文件dll_test.h的内容如下:
#ifndef HEADER_DLL_TEST_H
#define HEADER_DLL_TEST_H
#ifdef __cplusplus
extern "C" {
#endif
int add_function(int, int);
#ifdef __cplusplus
}
#endif
#endif
示例程序源文件dll_test.c的内容如下:
#include "dll_test.h"
int add_function(int x, int y)
{
return (x + y);
}
尝试生成dll文件,操作如下图:
在项目的Debug目录下,可以看到生成了以下文件:
启动Visual Studio命令提示,如下图:
执行命令: dumpbin /exports dll_test.dll,结果如下:
可以看到生成的dll_test.dll文件中没有任何可供外部调用的函数。为了能让 add_function( ) 能够被外部调用,有两种办法:
A)修改dll_test.h文件,在希望可被外部调用的函数声明前加上 __declspec(dllexport),修改后头文件内容如下:
#ifndef HEADER_DLL_TEST_H
#define HEADER_DLL_TEST_H
#ifdef __cplusplus
extern "C" {
#endif
__declspec(dllexport) int add_function(int, int);
#ifdef __cplusplus
}
#endif
#endif
重新生成dll文件,结果如下:
注意重新生成的文件数量比刚才多,多出了dll_test.exp和dll_test.lib文件。再次执行dumpbin /exports dll_test.dll ,结果如下:
可以看到现在dll_test.dll中提供了可供外部调用的add_function函数。如果执行执行dumpbin /exports dll_test.lib,结果如下:
B)如果不想修改dll_test.h文件,可以通过使用def文件来指定哪些函数可以被外部调用。添加def文件的过程如下图:
接下来在将要添加的文件类型列表中选择模块定义文件,如下图:
在新建的dll_test.def中添加以下内容:
特别注意:如果用户已经自己编写了def文件,应将它拷贝到dll_test.c文件所在目录下,然后在“解决方案资源管理器”子窗口中的“源文件”上点击鼠标右键,将现成的def文件添加进来,接下来在项目的属性页中必须按下图设置:
接下来重新生成,得到的文件如下:
使用dumpbin /exports 查看dll_test.dll和dll_test.lib,结果如下:
最后总结一下:
1. 后缀名为lib的文件可能是静态库,也可能是dll动态库对应的索引文件,不能看到lib后缀就认为该文件是静态库;
2. 当第三方程序使用隐式调用(即通过头文件、lib索引文件)方式使用dll中提供对外服务的函数时,在编译时只需要用到lib文件,在执行时只需要用到dll文件,第三方程序在执行时不再用到lib文件;
3. 在Visual Studio中,如果使用向导创建dll,在向导的“应用程序设置”这一步的“附加选项”中勾选了“空项目“,当不使用宏 __declspec(dllexport) 、也不使用def文件指定将要供外部访问的C函数时,在生成dll文件时不会生成对应的lib索引文件。如果需要生成lib索引文件,必须使用这两种方法之一。
4. 很多用户习惯自己编写def文件,如果要向项目中添加现成的def文件时,为了能让这个文件真正起作用,必须在项目属性中进行设置,即在项目属性页的 配置属性”->“链接器”->“输入”->“模块定义文件”中,输入def文件的名字。