1

我创建了一个 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();

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

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

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

但是,当我调用 MyFunc1() where MyFunc2() works时会发生运行时错误。

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

而且..它奏效了。

为什么 __stdcall 调用约定不能与 C# 中的 pinvoke 一起使用?

4

1 回答 1

7

What's happening here is that when you switch from __cdecl to __stdcall in the C++ code, the compiler decorates the name by which the function is exported. Instead of myFunc1 it is exported as myFunc1@0 or perhaps _myFunc1@0. All the same, the name is decorated. You can check that this is so with dumpbin or Dependency Viewer.

When you call GetProcAddress, it cannot find a function named myFunc1 and so returns NULL. You don't check for return values, and so carry on regardless. When you try to call the function, a run time error is thrown.

I've had to guess most of this because you did not show complete code. The other big lesson is to check for errors when calling Win32 functions.

于 2015-09-06T21:12:34.947 回答