stdcall调用约定和在c#中使用pinvoke
本文关键字:pinvoke 调用 约定 stdcall | 更新日期: 2023-09-27 18:11:22
我创建了一个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()。
和. .它工作。
为什么在c#中__stdcall调用约定不能与pinvoke一起工作?
这里发生的事情是,当您在c++代码中从__cdecl
切换到__stdcall
时,编译器会装饰导出函数的名称。而不是myFunc1
,它被导出为myFunc1@0
或_myFunc1@0
。尽管如此,名字还是有装饰的。你可以使用dumpbin
或Dependency Viewer来检查。
当调用GetProcAddress
时,它找不到名为myFunc1
的函数,因此返回NULL
。您不检查返回值,因此不顾一切地继续进行。当您尝试调用该函数时,会抛出一个运行时错误。
我不得不猜测大部分,因为你没有显示完整的代码。另一个重要的教训是在调用Win32函数时检查错误。