简体   繁体   中英

Memory issue in releasing memory in Callback from Objective C to C# in Unity application

I need to pass char* from Objective C to C# in Unity application. The issue now is when char* is released using free(), the application crash.

I have a callback function in Objective C side as

Unitybridge.mm

static UnityMultipleDevicesCallback MultipleDevicesLastCallBack = NULL;
void MultipleDevicesConnectCallback(UnityMultipleDevicesCallback callbackMethod)
{
    NSLog(@"callback is assigned");
    MultipleDevicesLastCallBack = callbackMethod;//a simple assignment using the connect method

}

void MultipleDevicesCallMethod(NSMutableArray *devices)
{
    NSLog(@"devices: %@", devices);
    if(MultipleDevicesLastCallBack != NULL){
        @autoreleasepool {
           devs_ = (char*)malloc([devices count]+1 * sizeof(char));

           for (NSString *s in devices) {

               if(strlen(devs_) > 0){
                   const char *d = "/";
                   strcat(devs_,d);
                   strcat(devs_, [s UTF8String] );
               }
               else{
                   strcpy(devs_, [s UTF8String]);
               }

           }           
        }

        MultipleDevicesLastCallBack(devs_);

    }
}
void Freedevs_()
{

    if(devs_!=nullptr){
        free(devs_);
        NSLog(@"devs_ is free now");
    }

}

At C# side,

     //
    [DllImport ("__Internal")]
    private static extern void Freedevs_();
    //Callback
    public delegate void UnityMultipleDevicesCallbackDelegate(string devices);
    [DllImport ("__Internal")]
    public static extern void MultipleDevicesConnectCallback(UnityMultipleDevicesCallbackDelegate callbackMethod);
    [MonoPInvokeCallback(typeof(UnityMultipleDevicesCallbackDelegate))]
    private static void MultipleDevicesCallback(string devices)
    {

        BLEdevices = (String)devices.Clone();
        Debug.Log ("Multiple devices callback now " + BLEdevices);
        //Freedevs_ ();
    }

I tried two options. One is @autoreleasepool and second one is without using @autoreleasepool , I call void Freedevs_() .

Using @autoreleasepool , not sure sometimes it works and sometimes the application crash. If I call Freedevs_ (), definitely the application crash.

What could be the solution for this?

I am fortunate that I found this article here .

According the article, I need to use [MarshalAs(UnmanagedType.LPStr)] at my C# side and updated. Please note that I don't use malloc anymore and that is sort of not reliable thing in such usage .

    Objectiv C
    void MultipleDevicesCallMethod(NSMutableArray *devices)
    {


      if(MultipleDevicesLastCallBack != NULL){
           NSString *d = @"";
           int cnt = 0;
           for (NSString *s in devices) {
               d = [d stringByAppendingString:s];
               if(cnt < [devices count]-1 &&  [devices count] > 1 ){
                   d = [d stringByAppendingString:@"/"];
                   cnt++;
               }

           }
           const char* devs_ =  [d cStringUsingEncoding:NSUTF8StringEncoding];
           MultipleDevicesLastCallBack(devs_);


      }       

    }

     C#
     public delegate void UnityMultipleDevicesCallbackDelegate(string devices);
    [DllImport ("__Internal", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
    public static extern void MultipleDevicesConnectCallback(UnityMultipleDevicesCallbackDelegate callbackMethod);
    [MonoPInvokeCallback(typeof(UnityMultipleDevicesCallbackDelegate))]
    private static void MultipleDevicesCallback([MarshalAs(UnmanagedType.LPStr)]string devices)
    {

        BLEdevices = (String)devices.Clone();
        Debug.Log ("Multiple devices callback now " + BLEdevices);
        Freedevs_ ();
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM