开发者

From C# how do I use a native C++ callback with an inherited struct?

From C# I need to setup a callback to C++ where the data received with the callback originates from structs with inheritance (See the distilled code below in the C++ section).

I believe the structs in C++ are collapsed by the compiler because they do not contain any virtual functions? So using the collapsed data class 'CollapsedCallbackInfo' in C# actually works for that specific data class. But having a lot of different data classes with multiple layers of inheritence in the real problem, is there a way solve this challenge? I need some common type to use in my delegate definition.

C#

Callback setup

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

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

C# Data classes

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

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

Collapsed data class

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

Test Class that illustrates the callback setup

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

   public void OnCallback(BaseCallbackInfo baseCallbackInfo)
   {
      // In the re开发者_JAVA技巧al problem I know this cast is valid
      ConcreteCallbackInfo ccbi = baseCallbackInfo as ConcreteCallbackInfo;
      Debug.Log(ccbi.concrete_data)
   }  
}

C++

Data classes

struct BaseCallbackInfo
{
   uint base_data;
};

struct ConcreteCallbackInfo : public BaseCallbackInfo
{
   uint concrete_data;
};

C-style Callback definition and external interface

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

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


Just define several DllImports of the same, e.g.

[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);

I would recommend you _stdcall instead of _cdecl.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜