0

我正在使用托管 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 供应商,我完全迷失在这里。

4

2 回答 2

5

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

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不理解?createDatabase@SdkDatabase@Artec@@$$FYA?AW4DatabaseResult@12@ABVSettings@12@AAPAViDatabase@12@@Z,但它们不同的部分(@@$$FYA?vs @@YG?)是调用约定(如果我更改YGYF,调用约定会更改,而没有其他内容)。

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

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

于 2013-03-12T18:44:26.083 回答
3

使用 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++、预处理器、预处理器定义设置。

于 2013-03-12T18:59:15.427 回答