Поднять события из C в C # (iOS для Unity) - PullRequest
0 голосов
/ 22 января 2019

Я хотел бы зарегистрироваться на события в Unity и поднять эти события из C в 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)
}

Будет ли это работать? Это правильный шаблон? Есть ли лучший способ сделать это?

Любые указатели для этого высоко ценятся.

Ответы [ 2 ]

0 голосов
/ 30 января 2019

Я решил это следующим шаблоном, и он работал безупречно. Надеюсь, это кому-нибудь поможет.

// 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
}
0 голосов
/ 30 января 2019

Unity предлагает использовать UnitySendMessage функцию для вызова метода C # из C.

. Вы можете использовать json для форматирования данных

NSDictionary *d = @{ @"data1":1, @"data2":2.0 };
NSData *j = [NSJSONSerialization dataWithJSONObject:d options:0 error:NULL];
NSString *s = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
UnitySendMessage("GameObjectName", "MethodName", [s UTF8String]);

. ВGameObject с именем GameObjectName , прикрепите скрипт с методом с именем MethodName .Используйте библиотеку json для декодирования строки в объект.

public class YourScriptName : Monobehaviour
{
    public class CBObj
    {
        public int data1;
        public float data2;
    }

    public void MethodName(string data)
    {
         var obj = UnityEngine.JsonUtility.FromJson<CBObj>(data);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...