【问题标题】:Decorated name for function generated improperly函数的修饰名称生成不当
【发布时间】:2017-05-12 17:17:10
【问题描述】:

我正在尝试使用 Visual Studio 2017(从 Visual Studio 6.0 升级)将一些第三方 C++ 代码编译到我的 32 位 C++ 应用程序中。我有来自第三方的 .h 文件和 .lib 文件。链接器正在查找库,但没有找到其中包含的修饰名称。这似乎是因为编译器正在用“char”替换“__int8”。

链接器错误是:

LNK2019   unresolved external symbol "signed char __cdecl Check_The_Thing(void)" (?Check_The_Thing@@YACXZ) referenced in function (redacted)

函数在.h中定义:

_declspec(dllexport) API_RETURN_TYPE  Check_The_Thing ( void );

API_RETURN_TYPE 定义在 .h:

_declspec(dllimport)   typedef signed   __int8   int_8;
_declspec(dllimport)   typedef          int_8    API_RETURN_TYPE;

使用 dumpbin /exports,我可以看到我的 lib 和关联的 dll 导出 Check_The_Thing:

?Check_The_Thing@@YA_DXZ (__int8 __cdecl Check_The_Thing(void))

使用 undname,我可以看到 lib 中的修饰名称正确评估:

Undecoration of :- "?Check_The_Thing@@YA_DXZ"
is :- "__int8 __cdecl Check_The_Thing(void)"

但是编译器生成的修饰名称没有正确评估(基于代码):

Undecoration of :- "?Check_The_Thing@@YACXZ"
is :- "signed char __cdecl Check_The_Thing(void)"

根据https://en.wikiversity.org/wiki/Visual_C%2B%2B_name_mangling,YACXZ 中的“C”计算为“signed char”,“_D”计算为“__int8”。我无法弄清楚为什么编译器将 API_RETURN_TYPE 解释为“char”而不是“__int8”。很明显,lib/dll 导出应该具有“_C”而不是“_D”,因为 API_RETURN_TYPE 是“签名的 __int8”,而不仅仅是“__int8”。

我已经摆弄了一堆编译器设置,但没有运气。正如这里 (Cannot find decorated function name in dll) 所建议的那样,我确定我使用的是 MBCS 而不是 Unicode(之前未设置),但这也没有任何区别。

将 API_RETURN_TYPE 专门定义为 __int8 没有区别,只是将“C”更改为“D”(进度!),同样 undname 将返回类型显示为“char”而不是“signed char”。将函数定义的返回类型更改为 __int8 与更改 API_RETURN_TYPE 的效果相同。

所以,我的问题是:如何强制编译器使用“__int8”(或“_D”)而不是 char(“D”)正确定义我的导出?

旁注:链接器错误在使用 __int16、__int32 和 __int64 的情况下是相同的。

编辑:实际上,该库定义了 __int64 类型,但我没有使用任何类型。没有任何 __int64 链接器错误。

【问题讨论】:

    标签: c++ visual-studio visual-studio-2017 name-decoration


    【解决方案1】:

    至少从 Visual Studio 2003 (!) 开始,"The __int8 data type is synonymous with type char"

    显然,编译器不能对命名同一类型的两种方法进行不同的名称修饰。

    this page 也很有见地,它表明__int8 是(签名的)char__int64 不是 long long;后者只是等价的。

    【讨论】:

    • 感谢您的回复。这也是我查到的资料。不过,如果它是同义词,我会认为链接器会将“_D”匹配到“D”。也许只有编译器才会这样。
    • @philselmer:这没有任何意义:因为它们是同义词,所以只能进行名称修改。就像long intlong 是一种类型的两个同义词一样,因此它们的排列方式相同。但是,没有理由假设 VS6 使用与 VS2017 相同的名称修饰。
    • 编译器正在做的是告诉链接器“_D”和“D”是相同的,所以它将使用“D”。但是链接器正在查找“_D”并且不理解它与“D”相同。如果 MS 要让编译器为 __int8 和 char 生成相同的重整名称,则链接器应该理解两者的重整名称。编辑:我想我期望 VS2003 和理解 _D 是不合理的,因为它们不再生成。
    猜你喜欢
    • 2018-10-25
    • 2017-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    • 2011-01-25
    相关资源
    最近更新 更多