diff options
author | Miguel de Icaza <miguel@gnome.org> | 2004-07-02 18:48:15 +0400 |
---|---|---|
committer | Miguel de Icaza <miguel@gnome.org> | 2004-07-02 18:48:15 +0400 |
commit | 2cf6798080ec4251faa5bc54b4e623464813a68b (patch) | |
tree | 5cb8f4869f253dec0b72231eb43755dd62f1948a | |
parent | 8dc9ab54ccd7e18ec93a60b2b436f881729e8974 (diff) |
Bring another patch from HEAD from Zoltan
svn path=/branches/mono-1-0/mono/; revision=30677
-rw-r--r-- | mono/metadata/ChangeLog | 5 | ||||
-rw-r--r-- | mono/metadata/marshal.c | 222 | ||||
-rw-r--r-- | mono/tests/libtest.c | 29 | ||||
-rwxr-xr-x | mono/tests/pinvoke2.cs | 18 |
4 files changed, 207 insertions, 67 deletions
diff --git a/mono/metadata/ChangeLog b/mono/metadata/ChangeLog index 03869d5b735..662605f6c5c 100644 --- a/mono/metadata/ChangeLog +++ b/mono/metadata/ChangeLog @@ -1,3 +1,8 @@ +2004-07-03 Zoltan Varga <vargaz@freemail.hu> + + * marshal.c: Fix managed->native stringbuilder marshalling. Implement + marshalling of stringbuilder arrays. Fixes #59900. + 2004-06-29 Martin Baulig <martin@ximian.com> * mono-debug.c (mono_debug_add_method): Protect the whole function diff --git a/mono/metadata/marshal.c b/mono/metadata/marshal.c index f15938d29c5..2892d81e88b 100644 --- a/mono/metadata/marshal.c +++ b/mono/metadata/marshal.c @@ -45,9 +45,6 @@ struct _MonoMethodBuilder { static void emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object); -static gint -mono_marshal_runtime_glist_find_klass (gconstpointer a, gconstpointer b); - static MonoMethod * mono_find_method_by_name (MonoClass *klass, const char *name, int param_count) { @@ -224,17 +221,20 @@ mono_string_builder_to_utf8 (MonoStringBuilder *sb) { GError *error = NULL; glong *res; + gchar *tmp; if (!sb) return NULL; res = g_malloc0 (mono_stringbuilder_capacity (sb) + 1); - g_utf16_to_utf8 (mono_string_chars (sb->str), sb->length, NULL, res, &error); + tmp = g_utf16_to_utf8 (mono_string_chars (sb->str), sb->length, NULL, res, &error); if (error) { g_error_free (error); mono_raise_exception (mono_get_exception_execution_engine ("Failed to convert StringBuilder from utf16 to utf8")); } + else + memcpy (res, tmp, sb->length + 1); return res; } @@ -1270,6 +1270,52 @@ mono_marshal_get_string_encoding (MonoMethodPInvoke *piinfo, MonoMarshalSpec *sp } } +static MonoMarshalNative +mono_marshal_get_stringbuilder_to_ptr_encoding (MonoMethodPInvoke *piinfo, MonoMarshalSpec *spec) +{ + MonoMarshalNative encoding = mono_marshal_get_string_encoding (piinfo, spec); + + switch (encoding) { + case MONO_NATIVE_LPWSTR: + return MONO_MARSHAL_CONV_SB_LPWSTR; + break; + case MONO_NATIVE_LPSTR: + return MONO_MARSHAL_CONV_SB_LPSTR; + break; + case MONO_NATIVE_LPTSTR: + return MONO_MARSHAL_CONV_SB_LPTSTR; + break; + default: + return -1; + } +} + +static MonoMarshalNative +mono_marshal_get_ptr_to_stringbuilder_encoding (MonoMethodPInvoke *piinfo, MonoMarshalSpec *spec, gboolean *need_free) +{ + MonoMarshalNative encoding = mono_marshal_get_string_encoding (piinfo, spec); + + *need_free = TRUE; + + switch (encoding) { + case MONO_NATIVE_LPWSTR: + /* + * mono_string_builder_to_utf16 does not allocate a + * new buffer, so no need to free it. + */ + *need_free = FALSE; + return MONO_MARSHAL_CONV_LPWSTR_SB; + case MONO_NATIVE_LPSTR: + return MONO_MARSHAL_CONV_LPSTR_SB; + break; + case MONO_NATIVE_LPTSTR: + return MONO_MARSHAL_CONV_LPTSTR_SB; + break; + default: + return -1; + } +} + static inline MonoMethod* mono_marshal_find_in_cache (GHashTable *cache, gpointer key) { @@ -1619,7 +1665,7 @@ mono_remoting_wrapper (MonoMethod *method, gpointer *params) } } - return mono_runtime_invoke (method, method->klass->valuetype? mono_object_unbox (this): this, mparams, NULL); + return mono_runtime_invoke (method, method->klass->valuetype? mono_object_unbox ((MonoObject*)this): this, mparams, NULL); } msg = mono_method_call_message_new (method, params, NULL, NULL, NULL); @@ -3392,31 +3438,22 @@ mono_marshal_get_native_wrapper (MonoMethod *method) mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_DEL_FTN); mono_mb_emit_stloc (mb, tmp_locals [i]); } else if (klass == mono_defaults.stringbuilder_class) { - MonoMarshalNative encoding = mono_marshal_get_string_encoding (piinfo, spec); + MonoMarshalNative encoding = mono_marshal_get_stringbuilder_to_ptr_encoding (piinfo, spec); g_assert (!t->byref); mono_mb_emit_ldarg (mb, argnum); mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); mono_mb_emit_byte (mb, CEE_MONO_FUNC1); - switch (encoding) { - case MONO_NATIVE_LPWSTR: - mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_SB_LPWSTR); - break; - case MONO_NATIVE_LPSTR: - mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_SB_LPSTR); - break; - case MONO_NATIVE_LPTSTR: - mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_SB_LPTSTR); - break; - default: { + if (encoding != -1) + mono_mb_emit_byte (mb, encoding); + else { char *msg = g_strdup_printf ("stringbuilder marshalling conversion %d not implemented", encoding); MonoException *exc = mono_get_exception_not_implemented (msg); g_warning (msg); g_free (msg); mono_raise_exception (exc); } - } mono_mb_emit_stloc (mb, tmp_locals [i]); } else { @@ -3512,10 +3549,13 @@ mono_marshal_get_native_wrapper (MonoMethod *method) else { MonoClass *eklass; guint32 label1, label2, label3; - int index_var, dest_ptr; + int index_var, dest_ptr, esize; + MonoMarshalNative encoding = mono_marshal_get_stringbuilder_to_ptr_encoding (piinfo, spec); dest_ptr = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg); + eklass = klass->element_class; + /* Check null */ mono_mb_emit_ldarg (mb, argnum); mono_mb_emit_stloc (mb, tmp_locals [i]); @@ -3524,9 +3564,23 @@ mono_marshal_get_native_wrapper (MonoMethod *method) label1 = mb->pos; mono_mb_emit_i4 (mb, 0); + if (eklass == mono_defaults.stringbuilder_class) { + if (encoding == -1) { + char *msg = g_strdup_printf ("stringbuilder marshalling conversion %d not implemented", encoding); + MonoException *exc = mono_get_exception_not_implemented (msg); + g_warning (msg); + g_free (msg); + mono_raise_exception (exc); + } + } + + if (eklass == mono_defaults.stringbuilder_class) + esize = sizeof (gpointer); + else + esize = mono_class_native_size (eklass, NULL); + /* allocate space for the native struct and store the address */ - eklass = klass->element_class; - mono_mb_emit_icon (mb, mono_class_native_size (eklass, NULL)); + mono_mb_emit_icon (mb, esize); mono_mb_emit_ldarg (mb, argnum); mono_mb_emit_byte (mb, CEE_LDLEN); mono_mb_emit_byte (mb, CEE_MUL); @@ -3551,22 +3605,34 @@ mono_marshal_get_native_wrapper (MonoMethod *method) /* Emit marshalling code */ - /* set the src_ptr */ - mono_mb_emit_ldarg (mb, argnum); - mono_mb_emit_ldloc (mb, index_var); - mono_mb_emit_byte (mb, CEE_LDELEMA); - mono_mb_emit_i4 (mb, mono_mb_add_data (mb, eklass)); - mono_mb_emit_byte (mb, CEE_STLOC_0); + if (eklass == mono_defaults.stringbuilder_class) { + mono_mb_emit_ldloc (mb, dest_ptr); + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_ldloc (mb, index_var); + mono_mb_emit_byte (mb, CEE_LDELEM_REF); + mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); + mono_mb_emit_byte (mb, CEE_MONO_FUNC1); + mono_mb_emit_byte (mb, encoding); + mono_mb_emit_byte (mb, CEE_STIND_I); + } + else { + /* set the src_ptr */ + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_ldloc (mb, index_var); + mono_mb_emit_byte (mb, CEE_LDELEMA); + mono_mb_emit_i4 (mb, mono_mb_add_data (mb, eklass)); + mono_mb_emit_byte (mb, CEE_STLOC_0); - /* set dst_ptr */ - mono_mb_emit_ldloc (mb, dest_ptr); - mono_mb_emit_byte (mb, CEE_STLOC_1); + /* set dst_ptr */ + mono_mb_emit_ldloc (mb, dest_ptr); + mono_mb_emit_byte (mb, CEE_STLOC_1); - /* emit valuetype conversion code */ - emit_struct_conv (mb, eklass, FALSE); + /* emit valuetype conversion code */ + emit_struct_conv (mb, eklass, FALSE); + } mono_mb_emit_add_to_local (mb, index_var, 1); - mono_mb_emit_add_to_local (mb, dest_ptr, mono_class_native_size (eklass, NULL)); + mono_mb_emit_add_to_local (mb, dest_ptr, esize); mono_mb_emit_byte (mb, CEE_BR); mono_mb_emit_i4 (mb, label2 - (mb->pos + 4)); @@ -3993,33 +4059,20 @@ mono_marshal_get_native_wrapper (MonoMethod *method) case MONO_TYPE_CLASS: case MONO_TYPE_OBJECT: if (t->data.klass == mono_defaults.stringbuilder_class) { - MonoMarshalNative encoding = mono_marshal_get_string_encoding (piinfo, spec); - gboolean need_free = TRUE; + gboolean need_free; + MonoMarshalNative encoding; + + encoding = mono_marshal_get_ptr_to_stringbuilder_encoding (piinfo, spec, &need_free); g_assert (!t->byref); + g_assert (encoding != -1); + mono_mb_emit_ldarg (mb, argnum); mono_mb_emit_ldloc (mb, tmp_locals [i]); mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); mono_mb_emit_byte (mb, CEE_MONO_PROC2); - switch (encoding) { - case MONO_NATIVE_LPWSTR: - mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPWSTR_SB); - /* - * mono_string_builder_to_utf16 does not allocate a - * new buffer, so no need to free it. - */ - need_free = FALSE; - break; - case MONO_NATIVE_LPSTR: - mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_SB); - break; - case MONO_NATIVE_LPTSTR: - mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPTSTR_SB); - break; - default: - g_assert_not_reached (); - } + mono_mb_emit_byte (mb, encoding); if (need_free) { mono_mb_emit_ldloc (mb, tmp_locals [i]); @@ -4134,13 +4187,17 @@ mono_marshal_get_native_wrapper (MonoMethod *method) } /* Character arrays are implicitly marshalled as [Out] */ - if ((klass->element_class == mono_defaults.char_class) || (t->attrs & PARAM_ATTRIBUTE_OUT)) { + if ((klass->element_class == mono_defaults.char_class) || (klass->element_class == mono_defaults.stringbuilder_class) || (t->attrs & PARAM_ATTRIBUTE_OUT)) { /* FIXME: Optimize blittable case */ MonoClass *eklass; guint32 label1, label2, label3; - int index_var, src_ptr; + int index_var, src_ptr, esize; eklass = klass->element_class; + if (eklass == mono_defaults.stringbuilder_class) + esize = sizeof (gpointer); + else + esize = mono_class_native_size (eklass, NULL); src_ptr = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg); /* Check null */ @@ -4166,22 +4223,53 @@ mono_marshal_get_native_wrapper (MonoMethod *method) /* Emit marshalling code */ - /* set the src_ptr */ - mono_mb_emit_ldloc (mb, src_ptr); - mono_mb_emit_byte (mb, CEE_STLOC_0); + if (eklass == mono_defaults.stringbuilder_class) { + gboolean need_free; + MonoMarshalNative encoding = mono_marshal_get_ptr_to_stringbuilder_encoding (piinfo, spec, &need_free); - /* set dst_ptr */ - mono_mb_emit_ldarg (mb, argnum); - mono_mb_emit_ldloc (mb, index_var); - mono_mb_emit_byte (mb, CEE_LDELEMA); - mono_mb_emit_i4 (mb, mono_mb_add_data (mb, eklass)); - mono_mb_emit_byte (mb, CEE_STLOC_1); + g_assert (encoding != -1); - /* emit valuetype conversion code */ - emit_struct_conv (mb, eklass, TRUE); + /* dest */ + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_ldloc (mb, index_var); + mono_mb_emit_byte (mb, CEE_LDELEM_REF); + + /* src */ + mono_mb_emit_ldloc (mb, src_ptr); + mono_mb_emit_byte (mb, CEE_LDIND_I); + + mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); + mono_mb_emit_byte (mb, CEE_MONO_PROC2); + + mono_mb_emit_byte (mb, encoding); + + if (need_free) { + /* src */ + mono_mb_emit_ldloc (mb, src_ptr); + mono_mb_emit_byte (mb, CEE_LDIND_I); + + mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); + mono_mb_emit_byte (mb, CEE_MONO_FREE); + } + } + else { + /* set the src_ptr */ + mono_mb_emit_ldloc (mb, src_ptr); + mono_mb_emit_byte (mb, CEE_STLOC_0); + + /* set dst_ptr */ + mono_mb_emit_ldarg (mb, argnum); + mono_mb_emit_ldloc (mb, index_var); + mono_mb_emit_byte (mb, CEE_LDELEMA); + mono_mb_emit_i4 (mb, mono_mb_add_data (mb, eklass)); + mono_mb_emit_byte (mb, CEE_STLOC_1); + + /* emit valuetype conversion code */ + emit_struct_conv (mb, eklass, TRUE); + } mono_mb_emit_add_to_local (mb, index_var, 1); - mono_mb_emit_add_to_local (mb, src_ptr, mono_class_native_size (eklass, NULL)); + mono_mb_emit_add_to_local (mb, src_ptr, esize); mono_mb_emit_byte (mb, CEE_BR); mono_mb_emit_i4 (mb, label2 - (mb->pos + 4)); diff --git a/mono/tests/libtest.c b/mono/tests/libtest.c index 1a2bcfb06e9..6a9bad00f5a 100644 --- a/mono/tests/libtest.c +++ b/mono/tests/libtest.c @@ -651,6 +651,9 @@ int mono_test_marshal_stringbuilder (char *s, int n) { const char m[] = "This is my message. Isn't it nice?"; + + if (strcmp (s, "ABCD") != 0) + return 1; strncpy(s, m, n); return 0; } @@ -698,6 +701,20 @@ mono_test_marshal_string_array (char **array) } int +mono_test_marshal_stringbuilder_array (char **array) +{ + if (strcmp (array [0], "ABC")) + return 1; + if (strcmp (array [1], "DEF")) + return 2; + + strcpy (array [0], "DEF"); + strcpy (array [1], "ABC"); + + return 0; +} + +int mono_test_marshal_unicode_string_array (gunichar2 **array, char **array2) { GError *error = NULL; @@ -1003,6 +1020,18 @@ mono_test_marshal_mixed_point (mixed_point pt) } int +mono_test_marshal_mixed_point_2 (mixed_point *pt) +{ + if (pt->x != 5 || pt->y != 6.75) + return 1; + + pt->x = 10; + pt->y = 12.35; + + return 0; +} + +int time_t_sizeof (void) { return sizeof (time_t); diff --git a/mono/tests/pinvoke2.cs b/mono/tests/pinvoke2.cs index 179f67d0f56..6dd5a7828a7 100755 --- a/mono/tests/pinvoke2.cs +++ b/mono/tests/pinvoke2.cs @@ -111,6 +111,9 @@ public class Tests { [DllImport ("libtest", EntryPoint="mono_test_marshal_unicode_string_array", CharSet=CharSet.Unicode)] public static extern int mono_test_marshal_unicode_string_array (string [] a1, [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStr)]string [] a2); + [DllImport ("libtest", EntryPoint="mono_test_marshal_stringbuilder_array")] + public static extern int mono_test_marshal_stringbuilder_array (StringBuilder [] a1); + [DllImport ("libtest", EntryPoint="mono_test_marshal_inout_array")] public static extern int mono_test_marshal_inout_array ([In, Out] int [] a1); @@ -413,6 +416,7 @@ public class Tests { static int test_0_marshal_stringbuilder () { StringBuilder sb = new StringBuilder(255); + sb.Append ("ABCD"); mono_test_marshal_stringbuilder (sb, sb.Capacity); String res = sb.ToString(); @@ -445,6 +449,20 @@ public class Tests { return mono_test_marshal_unicode_string_array (new String [] { "ABC", "DEF" }, new String [] { "ABC", "DEF" }); } + static int test_0_marshal_stringbuilder_array () { + StringBuilder sb1 = new StringBuilder ("ABC"); + StringBuilder sb2 = new StringBuilder ("DEF"); + + int res = mono_test_marshal_stringbuilder_array (new StringBuilder [] { sb1, sb2 }); + if (res != 0) + return res; + if (sb1.ToString () != "DEF") + return 5; + if (sb2.ToString () != "ABC") + return 6; + return 0; + } + static int test_0_last_error () { mono_test_last_error (5); if (Marshal.GetLastWin32Error () == 5) |