Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge branch 'utf8' into utf8_test

  • Loading branch information...
commit 1929cf60fab59fa0b8de1233d57ce64885332101 2 parents 3b65e66 + 1d890fd
Nayuta Taga authored
Showing with 58 additions and 14 deletions.
  1. +4 −4 Source/Generator.Rewrite/Program.cs
  2. +54 −10 Source/OpenTK/BindingsBase.cs
View
8 Source/Generator.Rewrite/Program.cs
@@ -371,10 +371,10 @@ static void EmitStringBuilderEpilogue(MethodDefinition wrapper, MethodDefinition
static void EmitStringParameter(MethodDefinition wrapper, TypeReference p, MethodBody body, ILProcessor il)
{
// string marshaling:
- // IntPtr ptr = Marshal.StringToHGlobalAnsi(str);
+ // IntPtr ptr = MarshalStringToPtr(str);
// try { calli }
// 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;
var variable_name = p.Name + "_string_ptr";
@@ -396,9 +396,9 @@ static void EmitStringEpilogue(MethodDefinition wrapper, MethodBody body, ILProc
var p = wrapper.Parameters[i].ParameterType;
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 v = body.Variables.First(m => m.Name == variable_name);
il.Emit(OpCodes.Ldloc, v.Index);
View
64 Source/OpenTK/BindingsBase.cs
@@ -145,7 +145,57 @@ protected static void MarshalPtrToStringBuilder(IntPtr ptr, StringBuilder sb)
}
/// <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.
/// </summary>
/// <returns>An unmanaged pointer to an array of null-terminated strings</returns>
@@ -163,12 +213,7 @@ protected static IntPtr MarshalStringArrayToPtr(string[] str_array)
for (int i = 0; i < str_array.Length; i++)
{
- IntPtr str = Marshal.StringToHGlobalAnsi(str_array[i]);
- if (str == IntPtr.Zero)
- {
- throw new OutOfMemoryException();
- }
-
+ IntPtr str = MarshalStringToPtr(str_array[i]);
Marshal.WriteIntPtr(ptr, i * IntPtr.Size, str);
}
}
@@ -176,10 +221,9 @@ protected static IntPtr MarshalStringArrayToPtr(string[] str_array)
}
/// <summary>
- /// Frees a string array that has previously been
- /// marshalled by <c>MarshalStringArrayToPtr</c>.
+ /// Frees a marshalled string that allocated by <c>MarshalStringArrayToPtr</c>.
/// </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>
protected static void FreeStringArrayPtr(IntPtr ptr, int length)
{
Please sign in to comment.
Something went wrong with that request. Please try again.