从C#我如何使用继承结构的本机C ++回调?

时间:2011-04-19 16:28:39

标签: c# c++ interop callback

从C#开始,我需要设置回调到C ++,其中使用回调接收的数据来自具有继承的结构(请参阅下面C ++部分中的提取代码)。

我相信编译器会崩溃C ++中的结构,因为它们不包含任何虚函数?因此,在C#中使用折叠数据类“CollapsedCallbackInfo”实际上适用于该特定数据类。但是在真正的问题中有很多不同的数据类和多层继承,有没有办法解决这个挑战? 我需要在委托定义中使用一些常用类型。

C#

回叫设置

[DllImport("NativeDLL", CallingConvention = CallingConvention.Cdecl)] 
public static extern void SetupCallback(CallbackFunc callback);

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void CallbackFunc(BaseCallbackInfo baseCallbackInfo);

C#数据类

[StructLayout(LayoutKind.Sequential)]
public class BaseCallbackInfo 
{
    public uint base_data;
};

[StructLayout(LayoutKind.Sequential)]
public class ConcreteCallbackInfo : BaseCallbackInfo 
{
    public uint concrete_data;
};   

折叠数据类

[StructLayout(LayoutKind.Sequential)]
public class CollapsedCallbackInfo 
{
    public uint base_data;
    public uint concrete_data;
};

说明回调设置的测试类

public class TestClass
{
   public void RegisterCallback()
   {    
      SetupCallback(new CallbackFunc(OnCallback));
   }

   public void OnCallback(BaseCallbackInfo baseCallbackInfo)
   {
      // In the real problem I know this cast is valid
      ConcreteCallbackInfo ccbi = baseCallbackInfo as ConcreteCallbackInfo;
      Debug.Log(ccbi.concrete_data)
   }  
}

C ++

数据类

struct BaseCallbackInfo
{
   uint base_data;
};

struct ConcreteCallbackInfo : public BaseCallbackInfo
{
   uint concrete_data;
};

C风格的回调定义和外部接口

typedef void( *CallbackFunc )( BaseCallbackInfo* in_pCallbackInfo );

extern "C"
__declspec(dllexport) void SetupCallback(CallbackFunc callback);    

1 个答案:

答案 0 :(得分:1)

只需定义几个相同的DllImports,例如

[DllImport("NativeDLL", EntryPoint="SetupCallback", CallingConvention = CallingConvention.Cdecl)] 
public static extern void SetupCallback_Base(BaseCallbackFunc callback);

[DllImport("NativeDLL", EntryPoint="SetupCallback", CallingConvention = CallingConvention.Cdecl)] 
public static extern void SetupCallback_Concrete1(Concrete1CallbackFunc callback);

[DllImport("NativeDLL", EntryPoint="SetupCallback", CallingConvention = CallingConvention.Cdecl)] 
public static extern void SetupCallback_Concrete2(Concrete2CallbackFunc callback);

我建议你使用_stdcall而不是_cdecl。