1

我正在尝试使用 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”。

我摆弄了一堆编译器设置,但没有运气。正如这里所建议的(在 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 链接器错误。

4

1 回答 1

0

至少从 Visual Studio 2003 (!) 开始,“__int8 数据类型与 char 类型同义”

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

这个页面很有见地,它显示的__int8是(签名)char__int64不是;后者仅仅是等价的。 long long

于 2017-05-12T21:53:40.103 回答