一般来说,从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. (转)Eclipse中junit框架的使用——单元测试

    [转]junit浅学笔记一 JUnit是一个回归测试框架(regression testing framework).Junit测试是程序员测试,即所谓白盒测试,因为程序员知道被测试的软件如何(How ...

  2. VC++ Bresenham画线实例

    附带百度链接:http://wenku.baidu.com/link?url=GP4uDkoyulgNxQy5djBBi-JB5BCrMWW6svMDhSfmzi_Qi1s6DhwJiCPHdMI2o ...

  3. Html+CSS命名规范:

     Html+CSS命名规范: 1.样式命名: 2.样式文件命名:

  4. MarkDown 格式生产类型

    -- 不默认换行, 真的结束, 包括格式设定,记得空一行. -- 学习参考地址如下, 讲的不好, 太复杂, 不适合新手. 有好读的更好. ** 但是江湖规矩 还是引用下吧 这是地址(http://wo ...

  5. Fxcop 初体验

    代码质量对于软件项目的成败很重要,这点我想大家都明白.那么在一个软件团队中如何保证代码质量呢?对于这个问题不同的人可能会有不同的答案,对于我而言我觉得做好两点代码质量基本就可以保证了: 1.代码规范( ...

  6. JAVA IDE下载地址

    Subclipse 各版本官网下载地址: http://subclipse.tigris.org/servlets/ProjectDocumentList?folderID=2240 Eclipse ...

  7. easyui-helloworld

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  8. ubuntu nginx 伪静态 设置

    简单的静态设置 1  vim nginx.conf // 修改nginx配置文件 server { .... root /usr/local/nginx/html; #nginx网站根目录 #下面这个 ...

  9. jquery放大镜插件与样式

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

  10. eclipse中DDMS的LOGcat只有一列level

    拷贝来源:http://www.cnblogs.com/kobe8/p/4620785.html http://stackoverflow.com/questions/25010393/eclipse ...