stdcall calling convention and using pinvoke in C#

本秂侑毒 提交于 2019-12-24 12:44:20

问题


I created a DLL file which includes two empty functions below.

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

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

In C#, I could call the functions using DLLImport attribute like below.

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

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

So I tried again directly with LoadLibrary() of kernel32.dll instead of DllImport attribute.

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

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

However a runtime error occurs when I call MyFunc1() where MyFunc2() works.

So I replaced __stdcall with __cdecl in C++, recompiled the DLL and then called MyFunc1() again in C#.

And.. It worked.

Why on earth doesn't __stdcall calling convention work with pinvoke in C#?


回答1:


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.



来源:https://stackoverflow.com/questions/32427445/stdcall-calling-convention-and-using-pinvoke-in-c-sharp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!