Returning a byte array from ObjC to C# script on ios

I’m trying to create a plugin that lets you grab images from the ALAssetLibrary in the photo album. I have the bytes for a jpeg, and I just need to return them back to my C# script.

Objective C

    UIImage *image = [UIImage imageWithCGImage: [asset thumbnail]];
    NSData* pictureData =  UIImageJPEGRepresentation (image, 1.0);    
    //failed attempt 1 return (const char*)[pictureData bytes];
    //failed attempt 2 return (unsigned char*)[pictureData bytes];
    return (Byte*)[pictureData bytes];

C# code:

DllImport ("__Internal")]
private static extern byte[] _getjpeg(string unique_id);

void applytexture() {
      System.Byte[] thebytes = _getjpeg("pleh");
      var texture = new Texture2D(1,1);
      Debug.Log("Bytes length is "+thebytes.Length);
      texture.LoadImage(thebytes);
      renderer.material.mainTexture = texture;
}

The Objective C code seems to run ok. But the length of the bytes I get back in C# is 16777217. No idea what it is, but its not the 12k I saw in the XCode debugger.

Thanks.

Well, it’s a problem to get unmanaged memory into managed code. I don’t know ObjC (only C++) so the i’m not familiar with the syntax of ObjC. It’s easier to do it the other way round. Pass a managed array to ObjC and fill the array. You need to set the array size either big enough, or you have to implement a query function to get the required size.

// C++
int __declspec(dllexport) GetImageData(const char **data, int size)
{
    // access the data array and copy the data. Make sure you don't exceed the size limit.
    // return the copied byte count
}

// C#
[DllImport ("myLib")]
private static extern int GetImageData(byte[] data, int size);

byte[] image_Data= new byte[MAX_SIZE];
int bytes_Copied = GetImageData(image_Data,image_Data.Length);

hope that helps a bit :wink: Maybe there’s a ObjC expert around

From the forum post “returning a byte array to c# from objc”:

Obj-C

Bundle is called PluginName.bundle

// int** is pointer to int array.
int GetBytes(int** dataPtr)
{
    int len = 5;
    unsigned char* data = (unsigned char*)malloc(len);
    for (int i = 0; i < len; i++)
            data *= i;*

// Don’t care about array type; cast to output pointer type.
dataPtr = (int)data;
return len;
}
# C#
[DllImport(“PluginName”, CallingConvention = CallingConvention.Cdecl)]
private static extern int GetBytes(out IntPtr p);
void Start()
{
IntPtr unmanagedPtr;
int len = GetBytes(out unmanagedPtr);
byte[] managedData = new byte[len];
Marshal.Copy(unmanagedPtr, managedData, 0, len);
for (int i = 0; i < len; i++)
Debug.Log(string.Format(“managedData[{0}]:{1}”, i, managedData*));*
// Free memory allocated from objc. You likely want to find a way to
// reuse memory instead of allocating frequently.
Marshal.FreeHGlobal(unmanagedPtr);
}