stdcall调用约定并在C#中使用pinvoke [英] stdcall calling convention and using pinvoke in C#
问题描述
我创建了一个DLL文件,其中包含下面的两个空函数.
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
}
在C#中,我可以使用如下所示的DLLImport
属性来调用函数.
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();
所以我直接用kernel32.dll的LoadLibrary()
而不是DllImport
属性再次尝试.
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();
但是,当我调用MyFunc1() MyFunc2()工作的地方时,会发生运行时错误.
However a runtime error occurs when I call MyFunc1() where MyFunc2() works.
所以我用C ++中的__cdecl
替换了__stdcall
,重新编译了DLL,然后在C#中再次调用了MyFunc1().
So I replaced __stdcall
with __cdecl
in C++, recompiled the DLL and then called MyFunc1() again in C#.
而且..有效.
为什么__stdcall调用约定不能在C#中与pinvoke一起使用?
推荐答案
在这里发生的是,当您在C ++代码中从__cdecl
切换到__stdcall
时,编译器会修饰该函数的导出名称.代替myFunc1
,它导出为myFunc1@0
或_myFunc1@0
.都一样,名字装饰.您可以使用dumpbin
或Dependency Viewer来检查是否是这种情况.
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.
当您调用GetProcAddress
时,它找不到名为myFunc1
的函数,因此返回NULL
.您无需检查返回值,因此无论如何都要继续.当您尝试调用该函数时,会引发运行时错误.
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.
由于您没有显示完整的代码,因此我不得不猜测其中的大部分内容.另一个重要的教训是在调用Win32函数时检查错误.
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.
这篇关于stdcall调用约定并在C#中使用pinvoke的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!