P/调用一个具有C#结构的C委托
本文关键字:结构 委托 一个 调用 | 更新日期: 2023-09-27 18:27:50
我正在尝试将以下C代码转换为C#。。。但我似乎在正确地将结构转换为回调时陷入了困境。编译良好,但在运行时堆栈不平衡。
C
INT32 RegisterCallback4ThirdParty(BtSdkCallbackStru* call_back);
typedef struct _CallbackStru
{
BTUINT16 type; /*type of callback*/
void *func; /*callback function*/
}CallbackStru, *PBCallbackStru;
以下是我的转换:
C#
[DllImport("SDK.dll")]
[return: MarshalAs(UnmanagedType.I4)]
public static extern Int32 RegisterCallback4ThirdParty(ref CallbackStru callback);
public class CallbackStru
{
public ushort type; //type of callback
public object func; //callback function
}
调用C#中的例程时:
CallbackStru cb = new CallbackStru();
AppInquiryInd appInquiryInd = AppInquiryInd;
cb.type = 0x04;
cb.func = appInquiryInd;
RegisterCallback4ThirdParty(ref cb);
AppInquiryId是该代表的位置:
public delegate void AppInquiryInd(UInt32 deviceHandle);
它在RegisterCallback4ThirdParty(ref cb)失败;
我只是忽略了什么吗?
干杯。
委托声明可能不正确,请尝试:
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void AppInquiryInd(UInt32 deviceHandle);
并且一定要声明要匹配的结构,以便可以正确地封送函数指针:
[StructLayout(LayoutKind.Sequential)]
private struct _BtSdkCallbackStru {
public ushort type; //type of callback
public AppInquiryInd func; //callback function
}
我将类更改为结构,现在ref参数是正确的:
[DllImport("SDK.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern int RegisterCallback4ThirdParty(ref CallbackStru callback);
堆栈不平衡是由缺少CallingConvention引起的。
此外,你必须确保委托对象对垃圾收集器保持可见,它看不到本地代码使用了它。这需要将它存储在一个静态字段中,或者使用GCHandle.Alloc()为它分配一个额外的句柄。因此,大致如下:
CallbackStru cb = new CallbackStru();
AppInquiryInd callback = new AppInquiryInd(myCallbackMethod);
ToCleanupLater = GCHandle.Alloc(callback);
cb.type = 0x04;
cb.func = callback;
RegisterCallback4ThirdParty(ref cb);
其中"ToCleanupLater"是一个占位符变量,因此当本机代码无法再进行回调时,可以调用GCHandle.Free()。如果没有停止回调的机制,那么就不用麻烦释放它了。