11

I am creating an iOS Plugin which needs to return a string (or const char*) to Unity. How do I implement it ?

2 Answers 2

9

I'd like to clarify previous answer. C# declaration:

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

Returning a string from objc is exactly like @Cabrra said:

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

Though some people mentioned that this way will lead to a memory leak that is not right. This way works fine in Unity and no leaks occurs (I tested it many times). Unity clearly states that

String values returned from a native method should be UTF–8 encoded and allocated on the heap. Mono marshalling calls free for strings like this.

Sign up to request clarification or add additional context in comments.

1 Comment

You can also use strdup. return strdup([nsString UTF8String]);
5
    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:""];
}

5 Comments

Remember to free the string again after the bytes are turned into a managed string or there will be memory leaks if you keep using malloc, the string needs to be freed in the c# code with Marshal.FreeHGlobal I believe.
"You need to return a copy of the c string so that Unity handles the memory and gets a valid value". Does it mean that Unity automatically handles memory management? I agree with @Chris that malloc needs be freed to avoid memory leaks. Chris how can I free the C-malloced memory within C#? Can you give more details about Marhsal.FreeGlobal?
cStringCopy helped me a lot for passing Objective-C NSString back to C# (Unity)
@AndreaGorrieri Only to clarify: the signature of _helloWorldString in C# code would be: static extern string _helloWorldString();. So the char* returns to Unity as a managed string and no free is needed, it will be deallocated automatically by the system.
BTW cStringCopy() is exactly the same as strdup() that's been in the standard C library since the late 1960's.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.