- Home /
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.
You should check out this stackoverflow answer http://answers.unity3d.com/questions/132083/returning-a-byte-array-from-objc-to-c-script-on-io.html
Answer by Bunny83 · Jun 20, 2011 at 05:08 AM
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 ;) Maybe there's a ObjC expert around
Thanks, will try that. I'm actually doing it in ObjC/C++, so what you've provided there is very close to how I would do it. I'm just a bit uncertain how I would work with the "data" variable you defined in the GetImageData() function. You defnined "data" with consts. So do I need to memory copy the image data into it, or can I do something like:
data = (const **char)[pictureData bytes];
I also wonder if should not be an unsigned *char in both the function parameter and in the above line?
Found also another helpful post: http://answers.unity3d.com/questions/34606/how-do-i-pass-arrays-from-c-to-c-in-unity-if-at-al.html
Answer by idbrii · Feb 13, 2021 at 12:39 AM
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] = 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[i]));
// Free memory allocated from objc. You likely want to find a way to
// reuse memory instead of allocating frequently.
Marshal.FreeHGlobal(unmanagedPtr);
}
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
Cannot receive URL Scheme with App not running 1 Answer
how to pass unicode text from C# to Objective-C 1 Answer
Capture and share image in IOS 0 Answers