【发布时间】:2015-09-06 19:31:26
【问题描述】:
我创建了一个 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++ 中将 __stdcall 替换为 __cdecl,重新编译 DLL,然后在 C# 中再次调用 MyFunc1()。
而且.. 它奏效了。
到底为什么 __stdcall 调用约定不能与 C# 中的 pinvoke 一起使用?
【问题讨论】:
-
DllImport是 P/Invoke。你到底想做什么? :DUnmanagedFunctionPointer将托管委托编组为非托管函数指针(顾名思义) - 它与调用 DLL 中的非托管函数无关。好吧,不是“什么都没有”——显然,你有一个可以从非托管方传递或接收的委托,但这不是你在这里想要做的。 -
另外,根据
UnmanagedFunctionPointer、if you do not specify a field name, UnmanagedFunctionPointerAttribute is ignored.的文档,我没有看到您指定任何名称。 -
是的,你是对的。这次我使用的是“kernel32.dll”的LoadLibrary()、FreeLibrary() 和GetProcAddress()。我没有发布其余代码,因为我认为这对于这里的专家来说只是基本的东西。
-
很抱歉问了这么一个基本的问题,但是UnmanagedFunctionPointer中的函数名怎么指定??我只是使用 Marshal.GetDelegateForFunctionPointer 获取指针,并在那里指定了名称。
-
GetDelegateForFunctionPointer需要第二个参数的类型。通过typeof(MyFunc1);-)
标签: c# c++ pinvoke calling-convention stdcall