stdcall调用约定并在C#中使用pinvoke [英] stdcall calling convention and using pinvoke in C#

查看:755
本文介绍了stdcall调用约定并在C#中使用pinvoke的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆