如果我声明这样的函数:
#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
,因此,如果我调用它们,则链接器应查找修饰后的名称,因为它是一个__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
。但是,当我们advapi32.dll
使用dumpbin /exports
命令查看导出时,我们看到一个未修饰的名称:
现在,advapi32.lib
使用dumpbin /headers advapi32.lib
命令仔细检查文件:
请注意说明undecorate
符,该说明符允许将修饰名称链接到未修饰的导出。您可以使用def
带有EXPORTS
包含未修饰名称的节的文件来为dll获得相同的结果。请参见本文章和这个答案的其他信息。
同样,以上所有内容仅对x86应用程序有效。x64位环境中的C函数链接时没有名称修饰:
C函数的修饰形式取决于其声明中使用的调用约定,如下表所示。这也是声明C ++代码具有外部“ C”链接时使用的修饰格式。默认的调用约定是__cdecl。请注意,在64位环境中,未修饰功能。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句