Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mono/metadata/ChangeLog5
-rw-r--r--mono/metadata/marshal.c222
-rw-r--r--mono/tests/libtest.c29
-rwxr-xr-xmono/tests/pinvoke2.cs18
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)