2

I am using Il2CppInspector to generate scaffolding for a Unity game. I am able to convert System.String (app::String in Il2CppInspector) to std::string using the functions provided below.

How would I reverse this process; how do I convert a std::string to System.String?

helpers.cpp

    // Helper function to convert Il2CppString to std::string
    std::string il2cppi_to_string(Il2CppString* str) {
        std::u16string u16(reinterpret_cast<const char16_t*>(str->chars));
        return std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>{}.to_bytes(u16);
    }
    // Helper function to convert System.String to std::string
    std::string il2cppi_to_string(app::String* str) {
        return il2cppi_to_string(reinterpret_cast<Il2CppString*>(str));
    }

In short, I am looking for a function that takes in a std::string and returns an app::String

    // Helper function to convert std::string to System.String
    app::String string_to_il2cppi(std::string str) {
        // Conversion code here
    }
8
  • Do you mean std::string to System.String instead? std::wstring_convert has a from_bytes() method Commented May 10, 2021 at 3:52
  • Whoops... yes. I meant std::string to System.String thank you for pointing that out. Will fix. Commented May 10, 2021 at 3:55
  • does this help you? stackoverflow.com/questions/13718188/… Commented May 11, 2021 at 12:36
  • or maybe this stackoverflow.com/questions/946813/… Commented May 11, 2021 at 12:36
  • Those do not work as I am not using CLR for this project. Commented May 12, 2021 at 5:41

2 Answers 2

0

The accepted answer is actually wrong, there is no size parameter and copying stops at the first null byte (0x00) according to the MSDN documentation.

The following code fixes these problems and works correctly:

app::String* string_to_il2cppi(const std::string& string)
{
    const auto encoding = (*app::Encoding__TypeInfo)->static_fields->utf8Encoding;

    const auto managed_string = app::String_CreateStringFromEncoding((uint8_t*)&string.at(0), string.size(), encoding, nullptr);

    return managed_string;
}

A quote from djkaty:

To create a string, you cannot use System.String‘s constructors – these are redirected to icalls that throw exceptions. Instead, you should use the internal Mono function String.CreateString. This function has many overloads accepting various types of pointer and array; an easy one to use accepts a uint16_t* to a Unicode string and can be called as follows [...]

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

5 Comments

Just because you can't get it to work doesn't mean it's wrong. And why did you edit my answer with an incorrect MSDN link? This is an Il2CppInspector question, thus Marshal_PtrToStringAnsi is exported using it, not a native call.
@UnAlpha: Exported functions are from the Unity game's assembly or from the .NET framework, in this case it's from the framework so the MSDN link was correct. See the example code which casts to a char * (= void *) and then to an IntPtr:docs.microsoft.com/en-us/dotnet/api/… Also obviously if your code fails to work for any input, it's wrong. You definitely need a size parameter, otherwise how would the code know when to stop? A 0x00 byte is not a terminator in std::strings. That cannot even possibly work in general.
"Cannot work in general" My game mod project uses it, and it does exactly what it says it does. I didn't come up with this - it was recommended to me on another forum and it's how they are converting std::string to System Strings aswell. - If you try it and couldn't get it working, my guess would be you haven't exported all namespaces in Il2cppInspector, and that your not using the exported project it prebuilds for you with said namespaces.
@UnAlpha: Buddy, you're implying I couldn't compile it but I could. It just produced faulty output unlike my version of the conversion function. I kept wondering why I crashed and this was the reason and I fixed it by using my version of the code instead. So actually try it on a std::string containing null bytes and tell me if it still works correctly or not lol: std::string test = "Hello\0world";
Okay it doesn't work with null terminators in the string, that's much different than saying it doesn't work in general. That's why I thought you couldn't get it to compile. I now understand why your method is better so I will mark it as the answer and put a notice of that limitation on my answer.
0

Export Il2CppInspector with all namespaces, which will give you access to Marshal_PtrToStringAnsi.

app::String* string_to_il2cppi(std::string str) {
    return app::Marshal_PtrToStringAnsi((void*)&str, NULL);
}

Limitation: do not attempt to convert a string with null terminators inside of them example:

std::string test = "Hello\0world";

Use BullyWiiPlaza's solution if this is an issue for you.

Comments

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.