mirror of
https://github.com/Ryujinx/Opentk.git
synced 2025-01-11 05:15:42 +00:00
Marshal strings as UTF8 (affects #18)
Starting with OpenGL 4.2, strings passed to GL.ShaderSource are allowed to contain multi-byte characters in comments (issue #18). This patch modifies the marshaling code to use UTF8.GetBytes in order to marshal strings, instead of Marshal.StringToHGlobalAnsi().
This commit is contained in:
parent
0c990583a3
commit
fd0c086e3d
|
@ -371,10 +371,10 @@ namespace OpenTK.Rewrite
|
||||||
static void EmitStringParameter(MethodDefinition wrapper, TypeReference p, MethodBody body, ILProcessor il)
|
static void EmitStringParameter(MethodDefinition wrapper, TypeReference p, MethodBody body, ILProcessor il)
|
||||||
{
|
{
|
||||||
// string marshaling:
|
// string marshaling:
|
||||||
// IntPtr ptr = Marshal.StringToHGlobalAnsi(str);
|
// IntPtr ptr = MarshalStringToPtr(str);
|
||||||
// try { calli }
|
// try { calli }
|
||||||
// finally { Marshal.FreeHGlobal(ptr); }
|
// finally { Marshal.FreeHGlobal(ptr); }
|
||||||
var marshal_str_to_ptr = wrapper.Module.Import(TypeMarshal.Methods.First(m => m.Name == "StringToHGlobalAnsi"));
|
var marshal_str_to_ptr = wrapper.Module.Import(TypeBindingsBase.Methods.First(m => m.Name == "MarshalStringToPtr"));
|
||||||
|
|
||||||
// IntPtr ptr;
|
// IntPtr ptr;
|
||||||
var variable_name = p.Name + "_string_ptr";
|
var variable_name = p.Name + "_string_ptr";
|
||||||
|
@ -396,9 +396,9 @@ namespace OpenTK.Rewrite
|
||||||
var p = wrapper.Parameters[i].ParameterType;
|
var p = wrapper.Parameters[i].ParameterType;
|
||||||
if (p.Name == "String" && !p.IsArray)
|
if (p.Name == "String" && !p.IsArray)
|
||||||
{
|
{
|
||||||
var free = wrapper.Module.Import(TypeMarshal.Methods.First(m => m.Name == "FreeHGlobal"));
|
var free = wrapper.Module.Import(TypeBindingsBase.Methods.First(m => m.Name == "FreeStringPtr"));
|
||||||
|
|
||||||
// Marshal.FreeHGlobal(ptr)
|
// FreeStringPtr(ptr)
|
||||||
var variable_name = p.Name + "_string_ptr";
|
var variable_name = p.Name + "_string_ptr";
|
||||||
var v = body.Variables.First(m => m.Name == variable_name);
|
var v = body.Variables.First(m => m.Name == variable_name);
|
||||||
il.Emit(OpCodes.Ldloc, v.Index);
|
il.Emit(OpCodes.Ldloc, v.Index);
|
||||||
|
|
|
@ -145,7 +145,57 @@ namespace OpenTK
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Marshals a string array to unmanaged memory by calling
|
/// Marshal a <c>System.String</c> to unmanaged memory.
|
||||||
|
/// The resulting string is encoded in UTF-8 and must be freed
|
||||||
|
/// with <c>FreeStringPtr</c>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="str">The <c>System.String</c> to marshal.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// An unmanaged pointer containing the marshalled string.
|
||||||
|
/// This pointer must be freed with <c>FreeStringPtr</c>
|
||||||
|
/// </returns>
|
||||||
|
protected static IntPtr MarshalStringToPtr(string str)
|
||||||
|
{
|
||||||
|
if (String.IsNullOrEmpty(str))
|
||||||
|
{
|
||||||
|
return IntPtr.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate a buffer big enough to hold the marshalled string.
|
||||||
|
// We use GetMaxByteCount() as it is faster than GetByteCount().
|
||||||
|
// The downside is that it may allocate up to 3x more memory than
|
||||||
|
// strictly necessary.
|
||||||
|
int max_count = Encoding.UTF8.GetMaxByteCount(str.Length) + 1;
|
||||||
|
IntPtr ptr = Marshal.AllocHGlobal(max_count);
|
||||||
|
if (ptr == IntPtr.Zero)
|
||||||
|
{
|
||||||
|
throw new OutOfMemoryException();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pin the managed string and convert it to UTF-8 using
|
||||||
|
// the pointer overload of System.Encoding.UTF8.GetBytes().
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
fixed (char* pstr = str)
|
||||||
|
{
|
||||||
|
int actual_count = Encoding.UTF8.GetBytes(pstr, str.Length, (byte*)ptr, max_count);
|
||||||
|
Marshal.WriteByte(ptr, actual_count, 0); // Append '\0' at the end of the string
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Frees a marshalled string that allocated by <c>MarshalStringToPtr</c>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ptr">An unmanaged pointer allocated with <c>MarshalStringToPtr</param>
|
||||||
|
protected static void FreeStringPtr(IntPtr ptr)
|
||||||
|
{
|
||||||
|
Marshal.FreeHGlobal(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Marshals a <c>System.String</c> array to unmanaged memory by calling
|
||||||
/// Marshal.AllocHGlobal for each element.
|
/// Marshal.AllocHGlobal for each element.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>An unmanaged pointer to an array of null-terminated strings</returns>
|
/// <returns>An unmanaged pointer to an array of null-terminated strings</returns>
|
||||||
|
@ -163,12 +213,7 @@ namespace OpenTK
|
||||||
|
|
||||||
for (int i = 0; i < str_array.Length; i++)
|
for (int i = 0; i < str_array.Length; i++)
|
||||||
{
|
{
|
||||||
IntPtr str = Marshal.StringToHGlobalAnsi(str_array[i]);
|
IntPtr str = MarshalStringToPtr(str_array[i]);
|
||||||
if (str == IntPtr.Zero)
|
|
||||||
{
|
|
||||||
throw new OutOfMemoryException();
|
|
||||||
}
|
|
||||||
|
|
||||||
Marshal.WriteIntPtr(ptr, i * IntPtr.Size, str);
|
Marshal.WriteIntPtr(ptr, i * IntPtr.Size, str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -176,10 +221,9 @@ namespace OpenTK
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Frees a string array that has previously been
|
/// Frees a marshalled string that allocated by <c>MarshalStringArrayToPtr</c>.
|
||||||
/// marshalled by <c>MarshalStringArrayToPtr</c>.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="ptr">An unmanaged pointer allocated by <c>MarshalStringArrayToPtr</c></param>
|
/// <param name="ptr">An unmanaged pointer allocated with <c>MarshalStringArrayToPtr</c></param>
|
||||||
/// <param name="length">The length of the string array.</param>
|
/// <param name="length">The length of the string array.</param>
|
||||||
protected static void FreeStringArrayPtr(IntPtr ptr, int length)
|
protected static void FreeStringArrayPtr(IntPtr ptr, int length)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue