【问题标题】:Unexpected calling convention for PInvokePInvoke 的意外调用约定
【发布时间】:2018-08-13 10:23:21
【问题描述】:

我在 dll 中有一个库及其头文件,但我没有它的源代码。 我需要使用 pinvoke 从 C# 调用此非托管代码,但在设置调用约定时遇到问题。头文件如下:

#ifdef EVOLIB_EXPORTS
#define EVOLIB_API __declspec(dllexport)
#else
#define EVOLIB_API __declspec(dllimport)
#endif
extern EVOLIB_API int ConvertRVBtoK(char *FileNameIn, char *FileNameOut,int ColorSmooth,int BlackMode);

我认为 ConvertRVBtoK 调用约定必须是 __cdecl 因为这是默认的 c/c++ 调用约定。但是,当我使用 undname.exe 实用程序检查修饰名称 ("?ConvertRVBtoK@@YGHPAEJJJ0E@Z") 时,结果显示 __stdcall 作为调用约定。为什么? dll文件和头文件有冲突吗?

【问题讨论】:

    标签: c# pinvoke calling-convention stdcall cdecl


    【解决方案1】:

    头文件根本没有指定调用约定。所以现在你依赖于编译器的默认值。它在 MSVC++ IDE 中使用 Project > Properties > C/C++ > Advanced > "Calling Convention" 设置进行配置。正如您所期望的那样,默认值为 /Gd,将其更改为 /Gz 作为 Q&D 修复程序并不少见。

    小心更改它,您可能会破坏其他在互操作代码中依赖 stdcall 的程序。请注意,您之前询问过 pascal 约定,即 32 位代码中的 stdcall。在头文件中显式,这样你就不会依赖编译器默认值也不会受到伤害。

    如果您没有源代码,那么您就无法更改它。 stdcall 没有什么特别的问题,它是 Windows 上预期的互操作默认值。

    【讨论】:

    • 所以,你的意思是任何人,谁写了这个 dll 和头文件,将默认 CallingConvention 设置为 __stdcall 然后构建项目。并且他/她没有在头文件中提及调用约定,并且假定 dll 的用户必须使用 undname.exe 与库进行互操作?我认为这是非常非常糟糕的做法。
    • 这确实不是一个好习惯。但是这个 DLL可能被明确地设计用于互操作,而不是用于 C 或 C++ 客户端程序。然后是 Q&D 修复,作者/构建工程师最有可能采取的捷径。有些语言不支持 stdcall 以外的任何东西,VBA 就是一个显着的例子。
    猜你喜欢
    • 1970-01-01
    • 2019-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-29
    • 2018-02-12
    • 1970-01-01
    • 2011-07-04
    相关资源
    最近更新 更多