c# - stdcall 调用约定和在 C# 中使用 pinvoke

标签 c# c++ pinvoke calling-convention stdcall

我创建了一个 DLL 文件,其中包含下面两个空函数。

extern "C" __declspec(dllexport) void __stdcall myFunc1() {
    // just empty function
}

extern "C" __declspec(dllexport) void __cdecl myFunc2() {
    // just empty function
}

在 C# 中,我可以使用 DLLImport 属性调用函数,如下所示。

[DllImport("myDLL", CallingConvention=CallingConvention.StdCall)]
private extern static void myFunc1();

[DllImport("myDLL", CallingConvention=CallingConvention.Cdecl)]
private extern static void myFunc2();

所以我再次尝试直接使用 kernel32.dll 的 LoadLibrary() 而不是 DllImport 属性。

[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void MyFunc1();

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void MyFunc2();

但是,当我调用 MyFunc1() MyFunc2() 起作用的地方 时发生运行时错误。

所以我用 C++ 中的 __cdecl 替换了 __stdcall,重新编译了 DLL,然后在 C# 中再次调用了 MyFunc1()。

而且..它起作用了。

到底为什么 __stdcall 调用约定不能与 C# 中的 pinvoke 一起工作?

最佳答案

这里发生的事情是,当您在 C++ 代码中从 __cdecl 切换到 __stdcall 时,编译器会修饰导出函数的名称。它不是 myFunc1,而是导出为 myFunc1@0_myFunc1@0。都一样,名字是装饰的。您可以使用 dumpbin 或 Dependency Viewer 检查是否如此。

当您调用 GetProcAddress 时,它找不到名为 myFunc1 的函数,因此返回 NULL。您不检查返回值,因此无论如何都要继续。当您尝试调用该函数时,将引发运行时错误。

我不得不猜测其中的大部分内容,因为您没有显示完整的代码。另一个重要的教训是在调用 Win32 函数时检查错误。

关于c# - stdcall 调用约定和在 C# 中使用 pinvoke,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32427445/

相关文章:

IEnumerable<IList<object>> 上的 C# foreach 编译但不应该

c++ - 在程序中创建一个值的界限

c++ - 抽象类c++的对象作为函数的参数

c++ - QDir::rename() 用于 2 个不同的分区

c# - 使用 CreateActCtx Win32 API 创建激活上下文

c# - 当 p/调用时,C/C++ 函数在 MonoTouch 中返回 NaN

c - 在 C DLL 中使用双 * 或短 *,在 C# 中使用 pinvoke 做什么

c# - 在 C++ 和 C# ByRef 之间传递字节数组引发 AccessViolationException

c# - 传递数组指针以放置在 C++ 中的 HashMap 中

c# - Math.Sinh() 在 C# 中返回不同的值