一般来说,从DLL导出函数有两种方法。一种是使用.def文件;另一种是使用__declspec(dllexport)。

使用上面两种方法各有优缺点。使用.def文件就是需要额外维护,当导出函数更改名字或者追加导出函数。而使用__declspec(dllexport)则需要注意使用的调用约定,在使用C++编译器时。

调用约定

在使用C++或者在常见的windows API的声明头文件常见的WINAPI,而WINAPA就是__stdcall。在C++还有__cdecl。而__pascal和__thiscall都已忽略了。宏PASCAL也用的是__stdcall。

一般来说,调用约定只关乎参数的压栈和最后的清理工作。还有就是名字修饰。比如:

void func(char, short, int, double)

使用__cdecl调用:

使用C编译器编译后的修饰名字为:_func。清理栈的工作由调用方做。

使用__stdcall和__thiscall调用:

使用C编译器编译后的修饰名字为_func@20。清理栈的工作由被调方做。

使用__fastcall调用:

使用C编译器编译后的修饰名字为@func@20。清理栈的工作由被调方做。

名字修饰

从上面的图也可看见,压栈都是从右到左,而名字修饰的方法却不一样。C编译器的修饰方法相对来说比较简单。以_func@20为例,_是追加的,func就是函数的名字,@是追加的,20为参数的字节数。C++的修饰方法相对来说比较复杂。下图是使用C++编译器产生的名字,使用__declspec(dllexport)和__stdcall。

下图是使用__cdecl编译:

大致一看都差不多,只是在名字后的有个字母不一样,__stdcall得是YG,而__cdecl的是YA。而这也正好指明了C++的名字修饰的规则,简单来说就是:

・名字(可以包含命名空间)

・调用约定

・返回值

・参数列表

调用约定修饰规则:

代号 调用约定
@@YG __stdcall
@@YA __cdecl
@@YI __fastcall

类型修饰规则:

代号 含义
X void
D char
E unsigned char
F short
H int
I unsigned int
J long
K unsigned long(DWORD)
M float
N double
_N bool
U struct
PA pointer
PB const pointer

参数表后以”@Z”标示整个名字的结束,如果该函数无参数,则以”Z”标识结束。

最后一点:如果我们直接使用__declspec(dllexport)导出函数的话,最好使用C编译器。如果直接用C++编译器,导出的函数名就像上面一样。在动态使用DLL时调用GetProcAddress使用原始函数名称一般来说会失败。例如:

GetProcAddress(handle, "func");

所以一般使用C编译器,比如这样:

#ifdef __cplusplus    // If used by C++ code
extern "C" { // we need to export the C interface
#endif __declspec(dllexport) VOID __cdecl func(char, short, int, double)
{
...
} #ifdef __cplusplus
}
#endif

这时,修饰后的名字就是这样:

一般导入函数时也建议这样:

#ifdef __cplusplus
extern "C" {
#endif // _declspec(dllimport) VOID func(char, short, int, double);
// or
VOID func(char, short, int, double); #ifdef __cplusplus
}
#endif

第一种写法在效率上来说会更好点。

参考:http://hi.baidu.com/luosiyong/item/c8664533f56b66c31b9696e3

http://msdn.microsoft.com/en-us/library/k2b2ssfy.aspx

DLL导出与调用约定的更多相关文章

  1. C/C++:函数的编译方式与调用约定以及extern “C”的使用

    转自:https://www.cnblogs.com/qinfengxiaoyue/archive/2013/02/04/2891908.html 函数在C++编译方式与C编译方式下的主要不同在于:由 ...

  2. DLL中调用约定和名称修饰(一)

    DLL中调用约定和名称修饰(一) 调用约定(Calling Convention)是指在程序设计语言中为了实现函数调用而建立的一种协议.这种协议规定了该语言的函数中的参数传送方式.参数是否可变和由谁来 ...

  3. 【原创+整理】简述何为调用约定,函数导出名以及extern C

    何为调用约定 调用约定指的是函数在调用时会按照不同规则,翻译成不同的汇编代码.这和参数的压栈顺序和栈的清理方式相关,也就是说不同的调用约定,这些方式会做相应改变.一般编译器是以默认的调用约定编译一份代 ...

  4. C/C++/动态链接库DLL中函数的调用约定与名称修饰

    参见:http://blog.twofei.com/cc/impl/calling-convension.html 调用约定(Calling Convention)是指在程序设计语言中为了实现函数调用 ...

  5. DLL导出函数和类的定义区别 __declspec(dllexport)

    DLL导出函数和类的定义区别 __declspec(dllexport) 是有区别的, 请看 : //定义头文件的使用方,是导出还是导入 #if defined(_DLL_API) #ifndef D ...

  6. C++调用约定和名字约定

    C++调用约定和名字约定 转自http://www.cppblog.com/mzty/archive/2007/04/20/22349.html 调用约定:__cdecl __fastcall与 __ ...

  7. dll 导出函数名的那些事

    dll 导出函数名的那些事 关键字: VC++  DLL  导出函数 经常使用VC6的Dependency或者是Depends工具查看DLL导出函数的名字,会发现有DLL导出函数的名字有时大不相同,导 ...

  8. c++builder调用VC的dll以及VC调用c++builder的dll

    解析__cdecl,__fastcall, __stdcall 的不同:在函数调用过程中,会使用堆栈,这三个表示不同的堆栈调用方式和释放方式. 比如说__cdecl,它是标准的c方法的堆栈调用方式,就 ...

  9. dll的概念 dll导出变量 函数 类

    1. DLL的概念 DLL(Dynamic Linkable Library),动态链接库,可以向程序提供一些函数.变量或类.这些可以直接拿来使用. 静态链接库与动态链接库的区别:   (1)静态链接 ...

随机推荐

  1. 参加魅族 flyme 互联网编程大赛的一些感受

    为期两天的 flyme 编程大赛已经结束了,自己也在这次大赛中深有感触,受益颇丰. 在这次大赛里,认识到了很多厉害的开发者,有单打独斗的,也有四五成群的.开幕致辞上看到很多非常有创意的点子,感觉每个队 ...

  2. Unity3D 之3D游戏SD快打 3D游戏基础入门开发全(1)

    这里记录一个U3D游戏,3D游戏的基本开发. 导入素材 1.首先导入需要的素材.因为FBX格式的素材是通用的,所以尽量导入这样的资源使用 导入后的结果: 然后对人形骨骼进行设置. 看哪里没有映射到骨骼 ...

  3. jjQuery 源码分析1: 整体结构

    目前阅读的是jQuery 1.11.3的源码,有参考nuysoft的资料. 原来比较喜欢在自己的Evernote上做学习基类,并没有在网上写技术博客的习惯,现在开始学习JS的开源代码,想跟大家多交流, ...

  4. thinkphp 自定义标签

    关于标签的个人理解是 拼凑php 字符串 通过eval()来进行,返回数据.过程应该是这样的,在模板中加入 定义标签为<mytag:list></mytag>,那么在mvc 中 ...

  5. linux 学习一

    linux 命令 ls -al ls -l cal

  6. eval(phpcode) 字符当代码执行

    eval(phpcode)eval() 函数把字符串按照 PHP 代码来计算.相当于在字符串两边分别加上PHP语 法标签 该字符串必须是合法的 PHP 代码,且必须以分号结尾. 如果没有在代码字符串中 ...

  7. c#语音

    1.新建WinForm程序,项目名称命名为Speech. 2.在COM组件中添加SpeechLib的引用. using SpeechLib;//添加语音引用 添加一个文本框并将其重命名为txtCont ...

  8. jquery放大镜插件与样式

    这是放大镜插件链接,我已经上传到我博客http://files.cnblogs.com/valiant1882331/%E6%94%BE%E5%A4%A7%E9%95%9C%E6%8F%92%E4%B ...

  9. jQuery设置checkbox全选(区别jQuery版本)

    jQuery设置checkbox全选在网上有各种文章介绍,但是为什么在我们用他们的代码的时候就没有效果呢? 如果你的代码一点错误都没有,先不要急着怀疑人家代码的正确性,也许只是人家跟你用的jQuery ...

  10. HTML 表格的书写方式:

    首先要进行reset  table{border-collapse:collapse;border-spacing:0;}th{text-align:inherit;} 1. caption标签对整个 ...