C++的64位名称修饰

8
我有一段代码,其中有以下代码行。
  #pragma comment(linker, "/include:_test@12") 

当我使用32位的C++Visual Studio 2010配置类型来编译代码时,使用该代码的项目正常工作(我也在一台32位的Windows机器上)。

当我将机器更改为64位并使用x64配置,用C++ Visual Studio 2010编译时,出现链接错误。

32位和64位的C++名称修饰不同吗?如果是这样,我在哪里可以找到64位C++名称修饰约定?

1个回答

10

是的,32位和64位之间的名称修饰是不同的。一个详细介绍确切格式的合理文章可以在这里找到。然而,你可以通过编译两个目标并检查生成的映射文件来快速区分主要差异。从我的经验来看,它们几乎相同(64位添加了一个小数据,可能会更改其他部分)。

简单示例:void foo();

32bit: ?foo@A@@QAEXXZ
64bit: ?foo@A@@QEAAXXZ

对于非混淆的std调用,长度后缀可能会有很大不同,这取决于参数堆栈使用情况。 VC++的默认64位设置不会添加下划线,也不会编码长度后缀。以下内容使用纯开箱即用设置在32/64位配置中进行了编译:

extern "C" int _stdcall func2(int, int, char*);

32bit: _func2@12
64bit: func2

没什么意义,是吧。

完成电路,未破坏的 _cdecl,它做了这个:

extern "C" int _cdecl func2(int, int, char*);

32bit: _func2
64bit: func2

如果看起来他们费尽心思让你知道你正在导入或导出什么,那么证据表明你很可能是正确的。


事实上,情况可能会非常不同...... 如果“test”接收三个指针参数,则它将从“12”更改为“24”......啊,还有这不是C ++函数。它似乎是一个“stdcall”C函数。 - Yakov Galka
我应该在哪里学习这些概念,因为我对它们很陌生。此外,我认为我的是stdcall,而你给出的示例是cdecl。我还有其他一些调用,例如#pragma comment(linker, "/export:test@0=test"),我应该如何更改它们?如果有一个参考资料能够澄清这些问题,那就太好了。 - user1612986
有大量关于C++名称修饰的文档(我给你链接了其中一个)。你似乎在使用extern "C" _stdcall导出,正如上面所示,在32位和64位中是不同的。MS和Wiki上有无数文章。虽然与VB相关,但我喜欢这篇文章,因为它做了一个不错的介绍。不管怎样,你都需要清理你的#pragma,用#ifdef WIN64导入或导出适当的名称。 - WhozCraig
据我所知,64位系统可用的调用约定只有vectorcall和默认的x64调用约定(从网上查到的信息来看,这似乎是fastcall的一个版本)。因此,在编译为64位时,__cdecl__stdcall__fastcall__thiscall都会被忽略。 - Justin Time - Reinstate Monica
维基百科页面已迁移到:https://en.wikiversity.org/wiki/Visual_C%2B%2B_name_mangling - Nulano

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接