Search code examples
c#objective-cunity-game-engineinteropservices

Sending float* from Objective C to C#


I am making a Unity project and trying to send float* array received at BLE (BlueTooth) at iPhone to C# code at Unity project.

Those function calls initiated from C# to C++ side to receive data by passing array is quite common. But here, this data transfer is initiated from Objective side to C# when data is received.

I used Plugin to interface to C#.

My Objective C side has

BLEObject.h, BLEObject.m, UnityBridge.h and UnityBridge.mm. UnityBridge is C++ code to interface to C#.

UnityBridge.h has

#ifdef __cplusplus
extern "C" {
#endif 
    void CallMethod(float* array);   

#ifdef __cplusplus
}
#endif

UnityBridge.mm has

#import "UnityBridge.h"    

void CallMethod(float* objectName)
{
    //some implementation here
}

BLEObject.h has

+(void) sendMessage:(NSData*)floatArray;

BLEObject.m has

+(void) sendMessage:(NSData*)floatArray 
{
    //I need to convert here NSData* to float array, how?
    CallMethod(floatArray);
}

When I receive data from BLE, I call [BLEObject sendMessage:floatArray] at Objective C side.

Then at C# side,

[DllImport ("__Internal")]
    public static extern void CallMethod (float* array);

Then I implement CallMethod as

public static void CallMethod (float* array){
    //reading array here

}

Actually this code doesn't work, but this is the flow I like to implement. How can I implement that?


Solution

  • Let me describe how I implement callback from Objective C to C#.

    Inside UnityBridge.h and UnityBridge.mm:
    
    typedef void (*UnityCommandCallback) ();
    
    #ifdef __cplusplus
    extern "C" {
    #endif
        void ConnectCallback(UnityCommandCallback callbackMethod);    
        void CallMethod();
    #ifdef __cplusplus
    }
    #endif
    
    #import "UnityBridge.h"
    //THis is the implementation of methods in the header file
    //A static variable to hold our function pointer
    static UnityCommandCallback LastCallBack = NULL;
    void ConnectCallback(UnityCommandCallback callbackMethod)
    {
        LastCallBack = callbackMethod;//a simple assignment using the connect method
    
    }
    
    void CallMethod()
    {
        if(LastCallBack != NULL)
            LastCallBack(/*objectName, methodName, parameter*/);
    }
    

    So this LastCallBack memorises the function to call back whenever the event happens at Objective C side.

    Inside BLEObject.h, BLEObject.m:
    

    On top of BLEObject.m, there is a decalaration.

    extern void CallMethod();
    

    So whenever, there is an event, you call this CallMethod(). Since the last call back function is memorised, it will always go back to the same place you want in C#.

    Inside C#: You have this

    public class BLEBridge : MonoBehaviour {
    
        public delegate void UnityCallbackDelegate(/*IntPtr objectName, IntPtr methodName, IntPtr parameter*/);
        [DllImport ("__Internal")]
        public static extern void ConnectCallback(UnityCallbackDelegate callbackMethod);
        [MonoPInvokeCallback(typeof(UnityCallbackDelegate))]
        private static void ManagedTest()
        {
            Debug.Log("IT WORKS!!!!");
        }
    }
    

    During the initialisation of the C# Object, we call this

    public static void TestSendMsg()
        {
            ConnectCallback (ManagedTest);
        }
    

    So Objective C side knows

    `ManagedTest()` is the function to call back whenever an event happens at Objective C side.
    

    That is how I implement Callback from Objective C going through C++ interface to C# Unity side.