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一起工作?

stdcall调用约定和在c#中使用pinvoke

这里发生的事情是,当您在c++代码中从__cdecl切换到__stdcall时,编译器会装饰导出函数的名称。而不是myFunc1,它被导出为myFunc1@0_myFunc1@0。尽管如此,名字还是有装饰的。你可以使用dumpbin或Dependency Viewer来检查。

当调用GetProcAddress时,它找不到名为myFunc1的函数,因此返回NULL。您不检查返回值,因此不顾一切地继续进行。当您尝试调用该函数时,会抛出一个运行时错误。

我不得不猜测大部分,因为你没有显示完整的代码。另一个重要的教训是在调用Win32函数时检查错误。