Unity iOS下将可变长度C字符串数组封送到C#的问题及解决
Objective-C 向 C# 返回字符串数组的问题解决
问题场景
需要从Objective-C向C#返回一组字符串,但始终无法正确实现,托管端打印返回的指针值为0。
初始错误代码
Objective-C
FOUNDATION_EXPORT int _GetAllKeys(char** pointer) { NSArray* array = @[@"key1", @"key2"]; // 测试字符串 int size = (int)array.count; pointer = malloc(size * sizeof(char *)); for (int i = 0; i < size; i++) { pointer[i] = MakeStringCopy(array[i]); } return size; }
C#
[DllImport("__Internal")] private static extern int _GetAllKeys(out IntPtr buffer); internal static IEnumerable<string> GetAllKeys() { int count = _GetAllKeys(out var buffer); List<string> keys = new List<string>(); for (int i = 0; i < count; i++) { keys.Add(Marshal.PtrToStringUTF8(IntPtr.Add(buffer, IntPtr.Size))); // 暂忽略编码问题 } return keys; }
错误原因分析
- Objective-C参数传递问题:
函数参数char** pointer是值传递,函数内pointer = malloc(...)仅修改了局部变量的指针值,外部传入的指针并未被更新,导致C#端接收到的buffer始终为0。 - C#字符串读取逻辑错误:
IntPtr.Add(buffer, IntPtr.Size)的偏移方式不正确,没有读取对应内存位置的字符串指针,无法正确获取每个字符串的地址。
正确解决方案代码
Objective-C
FOUNDATION_EXPORT int _GetAllKeys(char*** pointer) { NSArray* array = @[@"key1", @"key2"]; int size = (int)array.count; *pointer = malloc(size * sizeof(char *)); for (int i = 0; i < size; i++) { (*pointer)[i] = MakeStringCopy(array[i]); } return size; }
C#
[DllImport("__Internal")] private static extern int _GetAllKeys(out IntPtr buffer); internal static IEnumerable<string> GetAllKeys() { int count = _GetAllKeys(out var buffer); List<string> keys = new List<string>(); for (int i = 0; i < count; i++) { IntPtr ptr = Marshal.ReadIntPtr(buffer); keys.Add(Marshal.PtrToStringAuto(ptr)); buffer = IntPtr.Add(buffer, IntPtr.Size); } return keys; }
关键修改说明
- Objective-C端:使用
char*** pointer(指针的指针),通过*pointer修改外部传入的指针地址,确保C#端能获取到分配好的内存块指针;遍历赋值时操作(*pointer)[i],直接写入目标内存块。 - C#端:通过
Marshal.ReadIntPtr(buffer)读取当前位置的字符串指针,转换为字符串后,将buffer偏移IntPtr.Size,移动到下一个字符串指针的位置,完成遍历。
内容的提问来源于stack exchange,提问作者Magalek
相关产品推荐
相关产品推荐

