简体   繁体   English

C ++中无法解决的外部问题:Visual C ++操纵方法签名与dll中操纵方法不同

[英]Unresolved Externals in C++: Visual C++ mangles method signature differently from mangled method in dll

I'm using Visual Studio 2012, managed C++, to make a bridge between a third party SDK and our system which is written in C#. 我正在使用托管C ++的Visual Studio 2012在第三方SDK和我们用C#编写的系统之间架起一座桥梁。 I have succesfully wrapped and consumed several functions from said SDK. 我已经成功包装并使用了上述SDK中的几个功能。 Except one, which only result in a Unresolved External Error. 除了一个,只会导致一个未解决的外部错误。

The SDK's header file defines the function's signature: 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);

The error says: 错误提示:

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

So it's looking for the mangled name: 因此,它正在寻找名称混乱的名称:

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

Making a little dumpbin on the referenced dll, I found there is in fact a function called like that exported, thing is the name is mangled slightly different: 在引用的dll上做一些dumpbin,我发现实际上有一个名为export的函数,东西的名字有点不同:

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

Can anyone help me here? 有人能帮我一下吗? I cannot contact the SDK vendor, and I'm completely lost here. 我无法联系SDK供应商,我在这里完全迷路了。

The difference between those two lies in the calling convention section. 两者之间的区别在于调用约定部分。

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

The demangler I used does not understand ?createDatabase@SdkDatabase@Artec@@$$FYA?AW4DatabaseResult@12@ABVSettings@12@AAPAViDatabase@12@@Z , but the part where they differ ( @@$$FYA? vs @@YG? ) is the calling convention (if I change YG to YF , the calling convention changes and nothing else does). 我使用的 ?createDatabase@SdkDatabase@Artec@@$$FYA?AW4DatabaseResult@12@ABVSettings@12@AAPAViDatabase@12@@Z器无法理解?createDatabase@SdkDatabase@Artec@@$$FYA?AW4DatabaseResult@12@ABVSettings@12@AAPAViDatabase@12@@Z ,但是它们的区别( @@$$FYA? vs @@YG? )是调用约定(如果我将YG更改为YF ,则调用约定会更改,而没有其他操作)。

Change your declaration of the function to return-type __stdcall function-name[(argument-list)] . 将函数的声明更改为return-type __stdcall function-name[(argument-list)]

When you included the header file, did you #define USE_ADS_SHARED_LIB explicitly or on the compiler command line? 当包含头文件时,您是在显式还是在编译器命令行上#define USE_ADS_SHARED_LIB Are you targeting 32 bit windows? 您是否要定位32位窗口?

Use the undname.exe utility to undecorate names. 使用undname.exe实用程序取消修饰名称。 It is looking for: 它正在寻找:

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

The one you found is: 您找到的是:

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

Everything matches, except the calling convention, __cdecl vs __stdcall. 除调用约定__cdecl与__stdcall外,其他所有内容都匹配。 Note how the SDK header allows this to happen, it doesn't raise a stink when neither BUILD_ADS_SHARED_LIB nor USE_ADS_SHARED_LIB is #defined. 请注意,SDK标头是如何允许这种情况发生的,当BUILD_ADS_SHARED_LIB和USE_ADS_SHARED_LIB都未定义时,它不会发臭。 And that will produce a __cdecl function. 这将产生一个__cdecl函数。 Bad idea btw. 坏主意顺便说一句。

So very high odds that you simply forgot to define USE_ADS_SHARED_LIB. 您非常容易忘记定义USE_ADS_SHARED_LIB。 Project + Properties, C/C++, Preprocessor, Preprocessor Definitions setting. 项目+属性,C / C ++,预处理器,预处理器定义设置。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM