Open bugcaptor opened 8 years ago
This is a good catch.
In Mono, we assume that the default encoding does UTF-16 to UTF-8, but on the desktop Mono, the default is to use the platform-specific encoding, which is likely ANSI for these APIs.
So we probably need an attribute to configure custom marshaling on Windows to do the UTF-8 conversion (if the Urho API is taking UTF8 strings, which I am not sure it does).
I am also affected by this bug. I tried the following workaround but it does not work:
private static string EncodeStringForUrho(string str)
{
UTF8Encoding enc = new UTF8Encoding();
byte[] bytes = enc.GetBytes(str);
char[] buffer = new char[bytes.Length];
for (int i = 0; i < bytes.Length; ++i)
{
buffer[i] = (char)bytes[i];
}
return new string(buffer);
}
I guess the .NET marshaller does not simply use the low bytes of each C# char but applies some advanded logic that renders this workaround useless.
Someone has to fix the value of the DllImportAttribute.CharSet field that is generated by SharpieBinder so that it uses System.Runtime.InteropServices.CharSet.Unicode: https://github.com/xamarin/urho/blob/4c9df3372aae29370725ca3b66878482e58f066b/Bindings/Portable/Generated/Text.cs#L177
And the generated Text_SetText function should use the wchar_t override of the Urho3D::String constructor instead of the char version.
The bug also occurs with Text3D.
try hack the api, work for me
static class TextUnicodeFix
{
[DllImport("mono-urho", CallingConvention = CallingConvention.Cdecl)]
static extern void Text_SetText(IntPtr handle, byte[] text);
[DllImport("mono-urho", CallingConvention = CallingConvention.Cdecl)]
internal static extern void Text3D_SetText(IntPtr handle, byte[] text);
public static unsafe string GetTextFix(this Text text)
{
var foo = ((UrhoString*)(text.Handle + 472).ToPointer()); // 472 is offset of text_ in TextClass
return new string((sbyte*)foo->Buffer, 0, (int)foo->Length, Encoding.UTF8);
}
public static unsafe string GetTextFix(this Text3D text)
{
var foo = ((UrhoString*)(text.Handle + 748).ToPointer()); // 748 is offset of text_ in Text3DClass
return new string((sbyte*)foo->Buffer, 0, (int)foo->Length, Encoding.UTF8);
}
public static void SetTextFix(this Text text, string str)
{
var bytes = Encoding.UTF8.GetBytes(str);
Text_SetText(text.Handle, bytes);
}
public static void SetTextFix(this Text3D text, string str)
{
var bytes = Encoding.UTF8.GetBytes(str);
Text3D_SetText(text.Handle, bytes);
}
}
Me too.. hack above works for me, thanks!
On android it's OK, but on Windows desktop only shows "?" characters. For example CJK characters.
Maybe because of Mono's default encoding (UTF8) and C# default encoding (UTF16) difference? There is no code to convert utf16 to utf8 in marshalling.