Quick answer: Mismatched string encoding between native side and C# marshaling produces garbage. Use [MarshalAs(UnmanagedType.LPUTF8Str)] for UTF-8 char*, LPWStr for UTF-16. Or accept IntPtr and convert with Marshal.PtrToStringUTF8.

Here is how to fix Unity P/Invoke calls that return readable English in editor but garbled bytes for non-ASCII (or even for ASCII on some platforms). The default marshaling assumes ANSI; modern native code uses UTF-8.

The Symptom

Native function returns a string. C# receives a string but the contents are mojibake or appear cut off at non-ASCII.

What Causes This

Encoding mismatch. Default LPStr is ANSI, but most modern native code uses UTF-8.

Wide vs narrow. char* (1 byte) vs wchar_t* (2 or 4 bytes); marshaling must know which.

Lifetime issues. Native pointer freed before marshaling copies it.

The Fix

Step 1: Use UTF-8 marshaling.

using System.Runtime.InteropServices;

[DllImport("mylib")]
[return: MarshalAs(UnmanagedType.LPUTF8Str)]
private static extern string GetGreeting();

Step 2: For UTF-16 native.

[DllImport("mylib", CharSet = CharSet.Unicode)]
private static extern string GetWideText();

Step 3: For ownership control, return IntPtr.

[DllImport("mylib")]
private static extern IntPtr GetText();

public static string GetTextManaged()
{
    IntPtr p = GetText();
    return Marshal.PtrToStringUTF8(p);
}

Useful when the native side allocates and you need to free explicitly.

Step 4: Free if native owns and gives back ownership.

[DllImport("mylib")] static extern void FreeText(IntPtr p);

try
{
    return Marshal.PtrToStringUTF8(p);
}
finally
{
    FreeText(p);
}

Step 5: Test with a non-ASCII string. Verify with é, ü, or emoji. ASCII may pass even with wrong encoding; international content reveals the bug.

“Match the encoding. UTF-8 attribute or PtrToStringUTF8. Free if owned. Test with non-ASCII.”

Related Issues

For IL2CPP stripping, see IL2CPP Stripping. For BurstCompile, see Burst Compile.

UTF-8 attribute. PtrToStringUTF8. Test non-ASCII. Strings round-trip clean.