You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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;
}

错误原因分析

  1. Objective-C参数传递问题:
    函数参数char** pointer是值传递,函数内pointer = malloc(...)仅修改了局部变量的指针值,外部传入的指针并未被更新,导致C#端接收到的buffer始终为0。
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 20:05:31