Window创建并使用动态链接库

来源:互联网 发布:美国黑人知乎 编辑:程序博客网 时间:2024/05/27 09:47

1.关于导出符号

动态链接库给外部文件提供一些函数或变量,将这种提供函数或变量的行为称为导出符号。而外部文件使用这些函数或变量的行为则称为导入符号。在Linux 的ELF文件中,默认导出共享对象中的所有全局符号,而在 Windows 中的 DLL 中,则默认所有符号都不导出;因此,在 DLL 中需要显示的指定哪些符号是导出的符号,有以下两种方式指定一个符号是否导出:


1).__declspec 属性关键字

通过属性关键字 __declspec(dllexport) 来声明动态链接库文件中一个符号或函数是导出符号

通过属性关键字 __declspec(dllimport)来声明动态链接库文件中一个符号或函数是导入符号

2).模块定义文件 .def

模块定义文件用于控制链接过程,为链接器提供有关链接程序的导出符号,属性以及其他信息。定义方式下述


2.创建动态链接库

假设 DLL 库的源代码定义在 math.c 中,根据声明导出符号的方式不同,有以下两种对应的定义:

1)使用__declspec 属性关键字

/* math.c */__declspec(dllexport)double add(double a,double b){return a+b;}__declspec(dllexport)double sub(double a,double b){return a - b;}
编译方式如下:
cl /LDd math.c

其中 /LDd 指示声明 debug 版本的 DLL。/LD 指示声明 release 版本的DLL,不加任何参数默认生成 exe 可执行文件

2)使用模块定义文件:

使用模块定义文件,则在 math.c 的源文件中不需要指明函数的属性,即定义为普通定义:

/* math.c */double add(double a,double b){return a+b;}double sub(double a,double b){return a - b;}
定义对应的模块定义文件 math.def,如下:

LIBRARY mathEXPORTSaddsub
该文件声明动态链接库中的导出符号有 add 与 sub。编译生成动态链接库的命令如下:

cl /LD /DEF math.def math.c


通过上述的命令后,将生成四个文件, math.dll,math.obj,math.exp,math.lib 这四个文件,其中 math.dll 即是我们需要的DLL文件,Math.obj 则是编译的目标文件


3.使用动态链接库

程序使用DLL 的过程其实是导入过程,对于从其他DLL 导入的符号,需要使用 __declspec(dllimport) 指令来显示的声明某个符号为导入符号。这与ELF 中的情况不同,ELF 中使用一个外部符号时,不用额外声明。

假设我们定义 main.c  的文件来使用 math.dll 中的 sub 函数,源代码如下:

/* main.c */#include <stdio.h>__declspec(dllimport) double sub(double,double);int main(){printf("%f\n",sub(3,2.1));return 0;}


在编译时,通过如下指令来生成可执行文件:

cl /c main.c          //该命令指示编译器将 main.c 编译成目标文件 main.obj

link main.obj math.lib  //使用链接器将 main.obj 与math.lib 链接在一起产生一个可执行文件 main.exe

说明一下 math.lib ,“.lib”文件是一组目标文件的集合,其中并不真正包含 math.c 中的代码和数据,它是用来描述 math.dll 的导出符号,它包含了 main.o 链接 math.dll 时所需要的导入符号以及一部分 “桩”代码,又被称为“胶水”代码,以便将程序与DLL 粘合在一起。这种 .lib 文件又被称为导入库

linux 下的动态链接库的符号信息都包含在.so文件中,不需要再生成目标文件后再进行一次静态链接

0 0