【问题标题】:How to return string from native iOS plugin to unity?如何从原生 iOS 插件返回字符串统一?
【发布时间】:2016-05-05 10:07:19
【问题描述】:

我正在创建一个需要向 Unity 返回字符串(或 const char*)的 iOS 插件。如何实现?

【问题讨论】:

    标签: xcode unity3d


    【解决方案1】:

    我想澄清以前的答案。 C# 声明:

    [DllImport("__Internal")]
    private static extern string getString();
    

    从 objc 返回一个字符串就像@Cabrra 说的:

    char* convertNSStringToCString(const NSString* nsString)
    {
        if (nsString == NULL)
            return NULL;
    
        const char* nsStringUtf8 = [nsString UTF8String];
        //create a null terminated C string on the heap so that our string's memory isn't wiped out right after method's return
        char* cString = (char*)malloc(strlen(nsStringUtf8) + 1);
        strcpy(cString, nsStringUtf8);
    
        return cString;
    }
    
    extern "C" char* getString()
    {
        const NSString* str = @"string";
        return convertNSStringToCString(str);
    }
    

    虽然有人提到这种方式会导致内存泄漏,这是不对的。这种方式在 Unity 中运行良好,并且不会发生泄漏(我测试了很多次)。 Unity clearly states那个

    从本地方法返回的字符串值应该是 UTF-8 编码并在堆上分配。 Mono marshalling 对这样的字符串免费调用。

    【讨论】:

    • 您也可以使用strdupreturn strdup([nsString UTF8String]);
    【解决方案2】:
        extern "C"
    {
        int _pow2(int x)
        {
            // Just a simple example of returning an int value
            return x * x;
        }
    
        // Returns a char* (a string to Unity)
        char* _helloWorldString()
        {
            // We can use NSString and go to the c string that Unity wants
            NSString *helloString = @"Hello World";
            // UTF8String method gets us a c string. Then we have to malloc a copy to give to Unity. I reuse a method below that makes it easy.
            return cStringCopy([helloString UTF8String]);
        }
    
        // Here is an example of getting a string from Unity
        char* _combineStrings(const char* cString1, const char* cString2)
        {
            // This shows we can create two NSStrings* from the c strings from Unity
            NSString *string1 = CreateNSString(cString1);
            NSString *string2 = CreateNSString(cString2);
            NSString *combinedString = [NSString stringWithFormat:@"%@ %@", string1, string2];
            // Same as before, have to go to a c string and then malloc a copy of it to give to Unity
            return cStringCopy([combinedString UTF8String]);
        }
    }
    
    //I also like to include these two convenience methods to convert between c string and NSString*. You need to return a copy of the c string so that Unity handles the memory and gets a valid value.
    
    char* cStringCopy(const char* string)
    {
        if (string == NULL)
            return NULL;
    
        char* res = (char*)malloc(strlen(string) + 1);
        strcpy(res, string);
    
        return res;
    }
    
    // This takes a char* you get from Unity and converts it to an NSString* to use in your objective c code. You can mix c++ and objective c all in the same file.
    static NSString* CreateNSString(const char* string)
    {
        if (string != NULL)
            return [NSString stringWithUTF8String:string];
        else
            return [NSString stringWithUTF8String:""];
    }
    

    【讨论】:

    • 记得在字节转成托管字符串后再次释放字符串,否则继续使用malloc会出现内存泄漏,需要在c#代码中用Marshal.FreeHGlobal释放字符串我相信。
    • “您需要返回 c 字符串的副本,以便 Unity 处理内存并获取有效值”。这是否意味着 Unity 会自动处理内存管理?我同意@Chris 的观点,即需要释放 malloc 以避免内存泄漏。 Chris 我如何在 C# 中释放 C-malloced 内存?您能否提供有关 Marhsal.FreeGlobal 的更多详细信息?
    • cStringCopy 在将 Objective-C NSString 传回 C# (Unity) 方面帮助了我很多
    • @AndreaGorrieri 仅澄清一下:_helloWorldString 在 C# 代码中的签名将是:static extern string _helloWorldString();。所以char*作为托管string返回Unity,不需要空闲,系统会自动释放。
    • 顺便说一句 cStringCopy() 与自 1960 年代后期以来在标准 C 库中的 strdup() 完全相同。
    猜你喜欢
    • 1970-01-01
    • 2019-05-29
    • 2022-12-03
    • 2020-12-25
    • 1970-01-01
    • 2012-12-12
    • 2012-01-29
    • 1970-01-01
    相关资源
    最近更新 更多