您的位置:首页 > 其它

动态链接库DLL的函数导出

2014-01-07 17:14 197 查看

1、导出普通函数

为了让DLL导出一些函数,需要在每一个将要被导出的函数前添加标识符:_declspec(dllexport)如:

_declspec(dllexport) int add(int a,intb){return a+b;}

编译生成DLL后使用dumpbin查看的到

 Ordinal                   hint        RVA           name

1                    0     0001107D       ?add@@YAHHH@Z = @ILT+120(?add@@YAHHH@Z)

其中Ordinal信息:1是导出函数的序号

Hint:数字是提示码,该信息不重要。

RVA:列出的地址是导出函数在DLL模块中的位置

Name:是导出函数的名称。?add@@YAHHH@Z主要是重载函数的命名。参见重载函数的命名方式。

2、导出C++类

实际上在动态链接库中还可以导出C++的类例如:

#define DLL_EXPORT_declspec(dllexport)
Class DLL_EXPORTPoint{

         Public:

         Void output(int x,int y);

}

也可以单独导出类的的成员函数

Class Point{

         Public:

         Void DLL_EXPORT output(int x,int y);

}

3、导出类的名称问题。

         因为C++编译器会在编译的时候对名字进行改编。所以我们希望动态链接库文件在编译的时候,导出的函数的名称不要发生改变,为了实现这一目的,在定义导出函数时,需要加上限定符:extern”C”。双引号中的C一定要大写。该限定符会直接导出函数的名称而不加修改如add。

         优点:利用限定符extern”C”可以解决C++和C语言之间相互调用时的函数命名问题。

         缺点:不能用于导出一个类的成员还输,和重载函数。(C语言没有重载函数)。

4、不同语言之间的DLL调用

_cdecl是C和C++程序的缺省调用方式。但是在一些场合需要使用标准调用_stdcall。如delphi调用VC写的dll时要使用_stdcall的调用方式。但是使此时使用extern”C”将C++转变成C,但是标准调用会将名字改编。如add函数:_add@8,其中以下划线开始,add表示函数名,@8表示函数参数占的字节。  

5、调用冲突的解决办法

为解决函数名的改变问题,可以在DLL工程下面添加一个模块定义文件(.def)来解决名字改编问题。Def的文件内容为

LIBRARY DLLTest
EXPORTS
add
output
其中DLLTest为动态链接库的名称add和output为所要导出的函数名称。

但此时仍然不能解决函数重载问题,函数重载。因为def只能对应单一的问题,如果要解决此问题还是要根据改变后的名字该重新设定

如: "int __stdcalladd(int,int)"改编后的名字为:(?add@@YGHHH@Z)
 "float __stdcall add(float,float)" 改编后的名字为:(?add@@YGMMM@Z)
因此def文件应改写为:
LIBRARY DLLTest
EXPORTS
addInt =(?add@@YGHHH@Z)
addFloat =(?add@@YGMMM@Z)
def文件中的名字是唯一的,所以对应重载函数要写成不同的名字。
Def导出类比较麻烦,不建议使用def导出类,而是直接使用
Class declspec(dllexport)Point{
    Void _stdcalladd(int x,int y);
};的形式导出。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: