dll导出函数(摘)

时间:2024-03-07 12:21:52

目录

1.DLL中导出函数的方式有两种

2.查看dll导出函数;

3.__declspec(dllexport)和.def文件的区别。

 

1.DLL中导出函数的方式有两种:

方式一:在每一个函数声明前添加标识符: __declspec(dllexport)

比如:__declspec(dllexport) int add(int a, int b){return a+b;} 

在这种方式下,如果调用该dll的是一个c++程序(同一个编译器的版本)是没有问题的。但是,如果调用该dll是一个其它语言的程序(如C#、VB),则会出错。究其原因,是因为在C++中存在函数的重载,允许函数重名,因此在编译器生成dll的时候,为了区别重名的程序,会将其进行一定算法进行名称转换。例如,对于前面的add函数,实际的函数名称是如下形式。

    

因此,我们直接通过函数名add是无法找到该函数的,从而导致调用失败。为了解决这一问题,我们往往在函数前面再加一个extern "C",使用C方式的函数命名规则。

    extern "C" _declspec(dllexport) int add(int a, int b);

这样函数的名称就成add了。

    

 

方式二:采用模块定义(.def)文件声明导出函数

1、在项目中新建一个*.def文件;

2、.def文件一般格式:

;DllTestDef.lib : 导出DLL函数
;作者:----
LIBRARY DllTestDef
EXPORTS
Add @1
Sub @2

说明:

(1)LIBRARY语句说明.def文件相应的DLL;

(2)EXPORTS语句后列出要导出函数的名称。可以在.def文件中的导出函数名后加@n,表示要导出函数的序号为n(在进行函数调用时,这个序号将发挥其作用);

(3).def 文件中的注释由每个注释行开始处的分号 (;) 指定,且注释不能与语句共享一行。

3、最后记得在链接器选项中选中使用的def文件(默认情况下,添加def文件时会自动加上该选项,无需手动更改)。

 

2.查看dll导出函数;

查看dll的导出函数需要借助到dumpbin.exe,该工具由VS自带,位于[VS安装目录]\VC\bin目录下;

在控制台中执行命令:dumpbin /EXPORTS test.dll

如果遇到 link.exe-系统错误:”无法启动此程序,因为计算机中丢失mspdb100.dll。",在执行上述命令前,先在控制台中运行[VS安装目录]\VC\bin\vcvars32.bat便可解决;

3.__declspec(dllexport)和.def文件的区别。

 1、使用方式一需要在我们要导出的每一个函数前加上__declspec(dllexport),这么繁琐且程序易读性差;

2、使用.def的原因:

由于在定义DLL导出C++函数的时候根本没有标准,所以gcc有自己的导出规范,vc也有自己的导出规范。每个编译器导出的函数都不一样,所以产生了def文件。它试图规范每一个导出函数的名字。而且这些“编译器生成的函数修饰”是有作用的,比如它是_stdcall,或者是_fastcall,还有或者函数的参数个数和定义(注意C++是可以函数重载的),编译器不会无缘无故的加上这么多没有用的修饰名字。

最后指得一提的是,一般C/C++默认的调用方式是__cdecl,这种方式下需要调用方对函数清栈。如果对外提供api共其它非C++程序使用时,调用方会无法清栈而出错(C#会直接报函数声明不匹配的错误)。因此,对外提供api时还应该将接口声明为__stdcall,让api函数自己清栈。这也是Windows API前面都加上了一个WINAPI的宏的原因。

def文件还有许多其它的高级用法,要进一步了解的话,可以参看一下MS的官方文档:http://msdn.microsoft.com/zh-cn/library/28d6s79h(v=vs.80).aspx