简体   繁体   English

stdcall调用约定并在C#中使用pinvoke

[英]stdcall calling convention and using pinvoke in C#

I created a DLL file which includes two empty functions below. 我创建了一个DLL文件,其中包括下面的两个空函数。

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. 在C#中,我可以使用DLLImport属性调用函数,如下所示。

[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. 因此,我再次尝试使用kernel32.dll的LoadLibrary()代替DllImport属性。

[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 . 但是,当我在MyFunc2()工作的地方调用MyFunc1()时,会发生运行时错误。

So I replaced __stdcall with __cdecl in C++, recompiled the DLL and then called MyFunc1() again in C#. 因此,我在C ++中用__cdecl替换了__stdcall ,重新编译了DLL,然后在C#中再次调用了MyFunc1()。

And.. It worked. 和..它的工作。

Why on earth doesn't __stdcall calling convention work with pinvoke in C#? 为什么__stdcall调用约定在C#中不能与pinvoke一起使用?

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. 这里发生的事情是,当您在C ++代码中从__cdecl切换到__stdcall时,编译器会修饰导出函数的名称。 Instead of myFunc1 it is exported as myFunc1@0 or perhaps _myFunc1@0 . 代替myFunc1导出为myFunc1@0_myFunc1@0 All the same, the name is decorated. 都是一样的,名字装饰。 You can check that this is so with dumpbin or Dependency Viewer. 您可以使用dumpbin或Dependency Viewer进行检查。

When you call GetProcAddress , it cannot find a function named myFunc1 and so returns NULL . 当您调用GetProcAddress ,它找不到名为myFunc1的函数,因此返回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. 另一个重要的教训是在调用Win32函数时检查错误。

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

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