将事件从C提升到C#(iOS到Unity) [英] Raise events from C to C# (iOS to Unity)

查看:103
本文介绍了将事件从C提升到C#(iOS到Unity)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在Unity中注册事件,并在iOS中从C引发这些事件.

I would like to register for events in Unity and raise those events from C in iOS.

我有以下模式-

// Unity side register delegate and event handler
private delegate void CallbackDelegate(CBObj data);
public static event CallbackDelegate dataUpdatedEvent;

// for iOS
#if !UNITY_EDITOR && UNITY_IOS
[DllImport("__Internal")]
private static extern void PluginFunction(CallbackDelegate callback);
#endif

public CBObj {
    // marshal C objects to c# objects in the constructor here using the Ptr from C
}
[MonoPInvokeCallback(typeof(CallbackDelegate))]
static void CallbackMethod(CBObj dataPtr)
{
    if (dataUpdatedEvent != null)
    {
        CBObj obj = new CBObj(dataPtr);
        dataUpdatedEvent(obj);
    }
}

// Unity Usage
private CallbackDelegate evt;
void Start(){
    evt += updateEvent;
}
public void updateEvent(CBObj data){
    // do something with data everytime its called
}

// C code
extern "C" typedef void (*CallBackFuncP) (CBObj dataPtr);
typedef struct
{
    float *data1;
    int *data2;
} CBObj;
extern "C" {
    CallBackFuncP* cb;
    void PluginFunction(CallBackFuncP callback) {
        // store the the callback function pointer
        cb = callback;
    }
}
// raise the event somewhere in code
if (cb != NULL) {
    CBObj *test =  [[CBObj alloc] init];
    cb(test)
}

这项工作吗?这是正确的模式吗?有更好的方法吗?

Would this work? Is this the correct pattern? Is there a better way to do it?

任何做到这一点的指针都受到高度赞赏.

Any pointers to do this are highly appreciated.

推荐答案

我通过以下模式解决了该问题,并且它运行正常.希望这对某人有帮助.

I solved it by the following patter and it worked flawlessly. Hope this helps someone.

// Unity side register delegate and event handler
delegate void Internal_CallbackDelegate(IntPtr dataPtr);
public delegate void CallbackDelegate(CBObj data);
// The above pattern is to deal with pointer conversion from iOS to Unity
public static event CallbackDelegate DataUpdatedEvent;

// YourUnityKlass for iOS 
#if !UNITY_EDITOR && UNITY_IOS
    [DllImport("__Internal")]
    private static extern void PluginFunction(Internal_CallbackDelegate callback);
#endif
// Where this class is declared call in constructor
#if !UNITY_EDITOR && UNITY_IOS
    PluginFunction(CallbackMethod);
#endif

public CBObj {
    // marshal C objects to c# objects in the constructor here using the Ptr from C
    private IntPtr m_Ptr;
    internal CBObj(IntPtr ptr)
    {
        if (ptr == IntPtr.Zero)
            throw new ArgumentException("ptr may not be IntPtr.Zero");
        m_Ptr = ptr;
        // getDataFromC();
    }
    // get individual pointers by exposing them via C and mashall copy the data as per your needs 
}

[MonoPInvokeCallback(typeof(Internal_CallbackDelegate))]
static void CallbackMethod(IntPtr dataPtr)
{
    if (DataUpdatedEvent != null)
    {
        CBObj obj = new CBObj(dataPtr);
        DataUpdatedEvent(obj);
    }
}

// Unity Usage
void Start(){
    YourUnityKlass klass  = new YourUnityKlass();
    YourUnityKlass.DataUpdatedEvent += updateEvent;
}
public void updateEvent(CBObj data){
    // do something with data every time its called
}

// C header - code
typedef struct
{
    float *data1;
    int *data2;
} CBObj;
typedef void (*CallBackFuncP) (CBObj* dataPtr);
@interface CallbackWrapper : NSObject
{
@public
    CallBackFuncP _dataUpdate;
}
- (void) sendDataUpdate:(CBObj*) obj;
@end

// C - impl code
@implementation CallbackWrapper
-(void) sendDataUpdate:(CBObj*) objPtr
{
    if (_dataUpdate != NULL){
        _dataUpdate(objPtr);
    }
}
@end
extern "C" {
    void PluginFunction(CallBackFuncP callback) {
        // Create a swiftKlass to store your callback pointer
        CallbackWrapper* cb = [[SwiftKlass shared] getCallback];
        cb->_dataUpdate = callback;
    }
}
// Swift usage - Inside say SwiftKlass
@objc public func getCallback() -> CallbackWrapper {
    return self.cb
}

这篇关于将事件从C提升到C#(iOS到Unity)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆