【问题标题】:Unresolved Externals in C++: Visual C++ mangles method signature differently from mangled method in dllC++ 中未解决的外部:Visual C++ 破坏方法签名与 dll 中的破坏方法不同
【发布时间】:2013-03-12 18:06:17
【问题描述】:

我正在使用托管 C++ 的 Visual Studio 2012 在第三方 SDK 和我们用 C# 编写的系统之间架起一座桥梁。我已成功包装并使用了所述 SDK 中的几个功能。除了一个,它只会导致未解决的外部错误。

SDK的头文件定义了函数的签名:

#if defined WIN32
    #if defined BUILD_ADS_SHARED_LIB
        #define ADS_LINK_SPEC __declspec (dllexport)
        #define ADS_CALLING_CONVENTION __stdcall
    #elif defined USE_ADS_SHARED_LIB
        #define ADS_LINK_SPEC __declspec (dllimport)
        #define ADS_CALLING_CONVENTION __stdcall
    #else
        #define ADS_LINK_SPEC
        #define ADS_CALLING_CONVENTION
    #endif
#else
    #define ADS_LINK_SPEC
    #define ADS_CALLING_CONVENTION
#endif

DatabaseResult ADS_LINK_SPEC ADS_CALLING_CONVENTION
createDatabase(
    const Settings& settings, Artec::SdkDatabase::iDatabase *& instance);

错误提示:

Error   10  error LNK2028: unresolved token (0A000089) "enum Artec::SdkDatabase::DatabaseResult __cdecl Artec::SdkDatabase::createDatabase(class Artec::SdkDatabase::Settings const &,class Artec::SdkDatabase::iDatabase * &)" (?createDatabase@SdkDatabase@Artec@@$$FYA?AW4DatabaseResult@12@ABVSettings@12@AAPAViDatabase@12@@Z) referenced in function "private: static enum Artec::SdkDatabase::DatabaseResult __clrcall Broadway3dWrapper::Broadway3dWrapper::GetConn(wchar_t const *,wchar_t const *,wchar_t const *,wchar_t const *,char const *,class Artec::SdkDatabase::iDatabase * &)" (?GetConn@Broadway3dWrapper@1@$$FCM?AW4DatabaseResult@SdkDatabase@Artec@@PB_W000PBDAAPAViDatabase@34@@Z) C:\bioap\tfs\Identitum\Dev\src\BA.Identitum.Devices.Broadway3d\Broadway3dWrapper.obj    BA.Identitum.Devices.Brodway3D

所以它正在寻找损坏的名称:

?createDatabase@SdkDatabase@Artec@@$$FYA?AW4DatabaseResult@12@ABVSettings@12@AAPAViDatabase@12@@Z

在引用的dll上做了一个小dumpbin,我发现实际上有一个类似的函数被导出,只是名称略有不同:

?createDatabase@SdkDatabase@Artec@@YG?AW4DatabaseResult@12@ABVSettings@12@AAPAViDatabase@12@@Z

有人可以帮我吗?我无法联系 SDK 供应商,我完全迷路了。

【问题讨论】:

  • 尝试对名称进行解码(例如,参见gershnik.com/tips/vc.asp#undname),看看到底有什么不同。
  • 我希望您清楚您正在使用的 DLL 版本不是使用 先前 版本的 CL(VC++ 编译器)构建的。如果是这样,那么所有关于他们使用的修改算法的赌注都没有了(众所周知,主要版本之间会发生变化)。您确定您没有将 64 位导入库链接到 32 位应用程序,反之亦然?
  • 我确实解开了它。它与函数声明中的完全一样。 enum Artec::SdkDatabase::DatabaseResult Artec::SdkDatabase::createDatabase(class Artec::SdkDatabase::Settings const &,class Artec::SdkDatabase::iDatabase * &)
  • @WhozCraig:我使用的是 Windows 64 位。如何确保我正在编译为 32 位应用程序?
  • @WhozCraig:它确实是用以前的版本编译的,但我很幸运,修改是一样的。

标签: c++ visual-c++ dll visual-studio-2012 dynamic-linking


【解决方案1】:

这两者的区别在于调用约定部分。

createDatabase@SdkDatabase@Artec@@YG?AW4DatabaseResult@12@ABVSettings@12@AAPAViDatabase@12@@Z 是标准调用:enum Artec::SdkDatabase::DatabaseResult __stdcall Artec::SdkDatabase::createDatabase(class Artec::SdkDatabase::Settings const &,class Artec::SdkDatabase::iDatabase * &)

demangler I used 不理解 ?createDatabase@SdkDatabase@Artec@@$$FYA?AW4DatabaseResult@12@ABVSettings@12@AAPAViDatabase@12@@Z,但它们不同的部分(@@$$FYA?@@YG?)是调用约定(如果我将 YG 更改为 YF,调用约定会更改并且没有别的)。

将函数声明更改为return-type __stdcall function-name[(argument-list)]

当您包含头文件时,您是显式地#define USE_ADS_SHARED_LIB 还是在编译器命令行上?您的目标是 32 位窗口吗?

【讨论】:

  • 你编译的是 32 位还是 64 位?
  • 添加#define USE_ADS_SHARED_LIB 使其正确链接。谢谢!
【解决方案2】:

使用 undname.exe 实用程序取消装饰名称。它正在寻找:

enum Artec::SdkDatabase::DatabaseResult 
__cdecl 
Artec::SdkDatabase::createDatabase(
    class Artec::SdkDatabase::Settings const &,
    class Artec::SdkDatabase::iDatabase * &
)

你找到的是:

enum Artec::SdkDatabase::DatabaseResult 
__stdcall 
Artec::SdkDatabase::createDatabase(
    class Artec::SdkDatabase::Settings const &,
    class Artec::SdkDatabase::iDatabase * &
)

一切都匹配,除了调用约定,__cdecl vs __stdcall。请注意 SDK 标头是如何允许这种情况发生的,当 BUILD_ADS_SHARED_LIB 和 USE_ADS_SHARED_LIB 都不是 #defined 时,它不会引起恶臭。这将产生一个 __cdecl 函数。顺便说一句,这是个坏主意。

您忘记定义 USE_ADS_SHARED_LIB 的几率非常高。项目 + 属性、C/C++、预处理器、预处理器定义设置。

【讨论】:

  • 谢谢,你是对的,不幸的是我已经接受了@Yakk 的回答。是的,我也认为即使不发出警告也是一个非常糟糕的主意,但是告诉我的俄罗斯供应商;)
  • @Hans 第三个条件(未定义宏)显然适用于客户端代码静态链接到库的情况。我不认为这是“坏事”,尤其是如果静态链接是这个库最常见的使用模式。
  • 链接器不关心符号来自哪里。 dllimport 优化是微不足道的,不值得糟糕的错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-04-14
  • 2011-02-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-05
相关资源
最近更新 更多