将可变大小的字符串C数组编组为C#(Unity iOS)

huangapple go评论64阅读模式
英文:

Marshalling variable-sized string C array into C# (Unity iOS)

问题

我需要将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))); // 最终当我解决这个问题时,字符串将以UTF8返回,但现在它甚至没有到达这一行,所以忽略编码。
    }

    return keys;
}

---------------- 解决方案 ----------------

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;
}
英文:

I need to return a collection of strings from Objective-C to C# and can't wrap my head around how to do this properly. When I print the returned pointer on managed side its value is 0.

Objective-c

FOUNDATION_EXPORT int _GetAllKeys(char** pointer)
{
    NSArray* array = @[@&quot;key1&quot;, @&quot;key2&quot;]; // dummy strings
    
    int size = (int)array.count;

    pointer = malloc(size * sizeof(char *));
    
    for (int i = 0; i &lt; size; i++)
    {
        pointer[i] = MakeStringCopy(array[i]);
    }
    return size;
}

C#

[DllImport(&quot;__Internal&quot;)]
private static extern int _GetAllKeys(out IntPtr buffer);

internal static IEnumerable&lt;string&gt; GetAllKeys()
{
    int count = _GetAllKeys(out var buffer);
    List&lt;string&gt; keys = new List&lt;string&gt;();
    for (int i = 0; i &lt; count; i++)
    {
	keys.Add(Marshal.PtrToStringUTF8(IntPtr.Add(buffer, IntPtr.Size))); //eventually when i make this work the strings will be returned as UTF8 but for now its not even making it to this line, so ignore the encoding.
    }

    return keys;
}

---------------- SOLUTION ----------------

Objective-c

FOUNDATION_EXPORT int _GetAllKeys(char*** pointer)
{
    NSArray* array = @[@&quot;key1&quot;, @&quot;key2&quot;];  
    int size = (int)array.count;
    
    *pointer = malloc(size * sizeof(char *));

    for (int i = 0; i &lt; size; i++)
    {
        (*pointer)[i] = MakeStringCopy(array[i]);
    }
    
    return size;
}

C#

[DllImport(&quot;__Internal&quot;)]
private static extern int _GetAllKeys(out IntPtr buffer);

internal static IEnumerable&lt;string&gt; GetAllKeys()
{
	int count = _GetAllKeys(out var buffer);
	List&lt;string&gt; keys = new List&lt;string&gt;();
	for (int i = 0; i &lt; count; i++)
	{
		IntPtr ptr = Marshal.ReadIntPtr(buffer);
		keys.Add(Marshal.PtrToStringAuto(ptr));
		buffer = IntPtr.Add(buffer, IntPtr.Size);
	}

	return keys;
}

答案1

得分: 1

你正在尝试返回一个char**,所以C函数的参数需要是char***:

FOUNDATION_EXPORT int _GetAllKeys(char*** pointer)
{
   NSArray* array = @[@"key1", @"key2"]; // dummy strings
   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#代码看起来没问题,只是IntPtr.Add返回一个新的IntPtr,所以它应该是:

keys.Add(Marshal.PtrToStringUTF8(buffer));
buffer = IntPtr.Add(buffer, IntPtr.Size);
英文:

You are trying to return a char**, so the C function parameter needs to be a char***:

FOUNDATION_EXPORT int _GetAllKeys(char*** pointer)
{
   NSArray* array = @[@&quot;key1&quot;, @&quot;key2&quot;]; // dummy strings
   int size = (int)array.count;

   *pointer = malloc(size * sizeof(char *));

   for (int i = 0; i &lt; size; i++)
   {
       (*pointer)[i] = MakeStringCopy(array[i]);
   }
   return size;
}

The C# code looks fine, except that IntPtr.Add returns a new IntPtr, so it has to be:

keys.Add(Marshal.PtrToStringUTF8(buffer));
buffer = IntPtr.Add(buffer, IntPtr.Size);

huangapple
  • 本文由 发表于 2023年7月27日 17:21:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/76778283.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定