我正在尝试从第三方DLL执行一些方法(在这种特殊情况下,rdOnAllDone),用C语言编写,然后查看头文件,我发现了这个:
#ifndef TDECLSDONE
#ifdef STDCALL
#define CCON __stdcall
#else
#define CCON __cdecl
#endif
#define TDECLSDONE
#endif
#define DLLIMP __declspec (dllimport)
DLLIMP int CCON rdOnAllDone (void(CCON *)(int));
在调用一种调用此方法的方法之后,我做了这个:
[DllImport("sb6lib.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int rdOnAllDone(Delegate d);
public delegate void rdOnAllDoneCallbackDelegate();
private static void rdOnAllDoneCallback()
{
Console.WriteLine("rdOnAllDoneCallback invoked");
}
正确调用该方法,但我无法获取int参数。所以我尝试像这样添加输入参数int
[DllImport("sb6lib.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int rdOnAllDone(Delegate d);
public delegate void rdOnAllDoneCallbackDelegate(int number);
private static void rdOnAllDoneCallback(int number)
{
Console.WriteLine("rdOnAllDoneCallback invoked " + number);
}
但现在委托被调用了两次并且它崩溃了程序,出现以下错误“vshosts32.exe已停止工作”
调用此DLL方法的正确方法是什么?
编辑:忘记添加Main方法:
public static void Main()
{
rdOnAllDoneCallbackDelegate del3 = new rdOnAllDoneCallbackDelegate(rdOnAllDoneCallback);
rdOnAllDone(del3);
while (true)
{
Thread.Sleep(1000);
}
}
答案 0 :(得分:4)
要使这项工作正确,您需要做三件事:
所以这应该更好,根据需要进行调整:
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void rdOnAllDoneCallbackDelegate(int parameter);
[DllImport("sb6lib.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int rdOnAllDone(rdOnAllDoneCallbackDelegate d);
class Foo {
private static rdOnAllDoneCallbackDelegate callback; // Keeps it referenced
public static void SetupCallback() {
callback = new rdOnAllDoneCallbackDelegate(rdOnAllDoneCallback);
rdOnAllDone(callback);
}
private static void rdOnAllDoneCallback(int parameter) {
Console.WriteLine("rdOnAllDoneCallback invoked, parameter={0}", parameter);
}
}
答案 1 :(得分:1)
您的代理签名必须与本机回调的签名相匹配,同时必须正确设置UnmanagedFunctionPointerAttribute
。
在你的情况下如此:
[UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
public delegate void rdOnAllDoneCallbackDelegate(int parameter);
[DllImport("sb6lib.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int rdOnAllDone(rdOnAllDoneCallbackDelegate callback);
用法:
{
rdOnAllDone(rdOnAllDoneCallback);
}
private static void rdOnAllDoneCallback(int parameter)
{
Console.WriteLine("rdOnAllDoneCallback invoked, parameter={0}", parameter);
}