繁体   English   中英

DLL使用__stdcall没有名称装饰:为什么它甚至工作?

[英]DLL using __stdcall without name decoration: why does it even work?

如果我声明一个这样的函数:

#ifdef TEST_EXPORTS
#define TEST_API __declspec(dllexport)
#else
#define TEST_API __declspec(dllimport)
#endif

TESTAPI int __stdcall myadd(int a, int b);

DLL中的符号是_myadd@8 ,这对我来说非常有意义(在这里阅读其他问题几个小时后,就是这样)。

但是Windows库似乎做了不同的事情。 他们还使用__stdcall (伪装成WINAPI ),但DLL中的符号没有名称装饰。 如果上面的方法在windows libs中,那么符号就是myadd

我的猜测是他们使用def文件来对符号进行别名。 但是当我链接到其中一个DLL时,为什么我的链接器知道这个?

windows头文件用WINAPI声明这些WINAPI ,所以如果我调用它们,链接器应该查找装饰名称,因为它是一个__stdcall函数。 但不知何故,链接器知道删除名称装饰。

我试图通过编写一个小DLL并使用def文件删除名称修饰来复制它。 正如预期的那样,我发现链接器错误,因为链接器仍然在寻找装饰名称。 我在纯C中完成了这个,以确保c ++名称修改不会影响它。

编辑:澄清,MSVC 14.0 / VS2015,32位

这里有一些几乎无法记录的魔法。 让我们看看一些WIN32 API函数,比如RegQueryValueExW 它在winreg.h文件中定义如下:

WINADVAPI LSTATUS APIENTRY RegQueryValueExW(...);

其中WIADVAPI__declspec(dllimport)APIENTRY__stdcall命名约定的名字对象。 另请注意,标头中的所有函数都声明为extern "C" 所以无论如何,这个函数应该使用名称修饰,其DLL导出应该是_RegQueryValueExW@24 然而,当我们使用dumpbin /exports命令查看advapi32.dll导出时,我们看到一个未修饰的名称:

advapi出口

现在让我们使用dumpbin /headers advapi32.lib命令仔细检查advapi32.lib文件:

在此输入图像描述

请注意undecorate说明符,它允许将装饰名称链接到未装饰的导出。 您可以使用包含未修饰名称的EXPORTS部分的def文件为您的dll获得相同的结果。 有关其他信息,请参阅文章和此答案

此外,上面写的所有内容仅对x86应用程序有效。 x64位环境中的C函数没有名称修饰链接:

C函数的装饰形式取决于其声明中使用的调用约定,如下表所示。 这也是当C ++代码声明具有外部“C”链接时使用的装饰格式。 默认调用约定是__cdecl。 请注意,在64位环境中,函数未进行装饰。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM