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

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

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

问题

我需要将Objective-C中的字符串集合返回给C#,但我无法理解如何正确地完成这个任务。当我在托管端打印返回的指针时,它的值为0。

Objective-C部分代码如下:

  1. FOUNDATION_EXPORT int _GetAllKeys(char** pointer)
  2. {
  3. NSArray* array = @[@"key1", @"key2"]; // 虚拟字符串
  4. int size = (int)array.count;
  5. pointer = malloc(size * sizeof(char *));
  6. for (int i = 0; i < size; i++)
  7. {
  8. pointer[i] = MakeStringCopy(array[i]);
  9. }
  10. return size;
  11. }

C#部分代码如下:

  1. [DllImport("__Internal")]
  2. private static extern int _GetAllKeys(out IntPtr buffer);
  3. internal static IEnumerable<string> GetAllKeys()
  4. {
  5. int count = _GetAllKeys(out var buffer);
  6. List<string> keys = new List<string>();
  7. for (int i = 0; i < count; i++)
  8. {
  9. keys.Add(Marshal.PtrToStringUTF8(IntPtr.Add(buffer, IntPtr.Size))); // 最终当我解决这个问题时,字符串将以UTF8返回,但现在它甚至没有到达这一行,所以忽略编码。
  10. }
  11. return keys;
  12. }

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

Objective-C部分代码如下:

  1. FOUNDATION_EXPORT int _GetAllKeys(char*** pointer)
  2. {
  3. NSArray* array = @[@"key1", @"key2"];
  4. int size = (int)array.count;
  5. *pointer = malloc(size * sizeof(char *));
  6. for (int i = 0; i < size; i++)
  7. {
  8. (*pointer)[i] = MakeStringCopy(array[i]);
  9. }
  10. return size;
  11. }

C#部分代码如下:

  1. [DllImport("__Internal")]
  2. private static extern int _GetAllKeys(out IntPtr buffer);
  3. internal static IEnumerable<string> GetAllKeys()
  4. {
  5. int count = _GetAllKeys(out var buffer);
  6. List<string> keys = new List<string>();
  7. for (int i = 0; i < count; i++)
  8. {
  9. IntPtr ptr = Marshal.ReadIntPtr(buffer);
  10. keys.Add(Marshal.PtrToStringAuto(ptr));
  11. buffer = IntPtr.Add(buffer, IntPtr.Size);
  12. }
  13. return keys;
  14. }
英文:

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

  1. FOUNDATION_EXPORT int _GetAllKeys(char** pointer)
  2. {
  3. NSArray* array = @[@&quot;key1&quot;, @&quot;key2&quot;]; // dummy strings
  4. int size = (int)array.count;
  5. pointer = malloc(size * sizeof(char *));
  6. for (int i = 0; i &lt; size; i++)
  7. {
  8. pointer[i] = MakeStringCopy(array[i]);
  9. }
  10. return size;
  11. }

C#

  1. [DllImport(&quot;__Internal&quot;)]
  2. private static extern int _GetAllKeys(out IntPtr buffer);
  3. internal static IEnumerable&lt;string&gt; GetAllKeys()
  4. {
  5. int count = _GetAllKeys(out var buffer);
  6. List&lt;string&gt; keys = new List&lt;string&gt;();
  7. for (int i = 0; i &lt; count; i++)
  8. {
  9. 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.
  10. }
  11. return keys;
  12. }

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

Objective-c

  1. FOUNDATION_EXPORT int _GetAllKeys(char*** pointer)
  2. {
  3. NSArray* array = @[@&quot;key1&quot;, @&quot;key2&quot;];
  4. int size = (int)array.count;
  5. *pointer = malloc(size * sizeof(char *));
  6. for (int i = 0; i &lt; size; i++)
  7. {
  8. (*pointer)[i] = MakeStringCopy(array[i]);
  9. }
  10. return size;
  11. }

C#

  1. [DllImport(&quot;__Internal&quot;)]
  2. private static extern int _GetAllKeys(out IntPtr buffer);
  3. internal static IEnumerable&lt;string&gt; GetAllKeys()
  4. {
  5. int count = _GetAllKeys(out var buffer);
  6. List&lt;string&gt; keys = new List&lt;string&gt;();
  7. for (int i = 0; i &lt; count; i++)
  8. {
  9. IntPtr ptr = Marshal.ReadIntPtr(buffer);
  10. keys.Add(Marshal.PtrToStringAuto(ptr));
  11. buffer = IntPtr.Add(buffer, IntPtr.Size);
  12. }
  13. return keys;
  14. }

答案1

得分: 1

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

  1. FOUNDATION_EXPORT int _GetAllKeys(char*** pointer)
  2. {
  3. NSArray* array = @[@"key1", @"key2"]; // dummy strings
  4. int size = (int)array.count;
  5. *pointer = malloc(size * sizeof(char *));
  6. for (int i = 0; i < size; i++)
  7. {
  8. (*pointer)[i] = MakeStringCopy(array[i]);
  9. }
  10. return size;
  11. }

C#代码看起来没问题,只是IntPtr.Add返回一个新的IntPtr,所以它应该是:

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

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

  1. FOUNDATION_EXPORT int _GetAllKeys(char*** pointer)
  2. {
  3. NSArray* array = @[@&quot;key1&quot;, @&quot;key2&quot;]; // dummy strings
  4. int size = (int)array.count;
  5. *pointer = malloc(size * sizeof(char *));
  6. for (int i = 0; i &lt; size; i++)
  7. {
  8. (*pointer)[i] = MakeStringCopy(array[i]);
  9. }
  10. return size;
  11. }

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

  1. keys.Add(Marshal.PtrToStringUTF8(buffer));
  2. 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:

确定