static void
emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object);
+static void
+emit_struct_conv_full (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object, MonoMarshalNative string_encoding);
+
static void
mono_struct_delete_old (MonoClass *klass, char *ptr);
return mono_marshal_string_to_utf16;
case MONO_MARSHAL_CONV_LPWSTR_STR:
return mono_string_from_utf16;
- case MONO_MARSHAL_CONV_LPSTR_STR:
+ case MONO_MARSHAL_CONV_LPTSTR_STR:
#ifdef TARGET_WIN32
return mono_string_from_utf16;
#else
return mono_string_new_wrapper;
#endif
+ case MONO_MARSHAL_CONV_LPSTR_STR:
+ return mono_string_new_wrapper;
case MONO_MARSHAL_CONV_STR_LPTSTR:
#ifdef TARGET_WIN32
return mono_marshal_string_to_utf16;
}
static void
-emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object)
+emit_struct_conv_full (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object,
+ MonoMarshalNative string_encoding)
{
MonoMarshalType *info;
int i;
case MONO_TYPE_R8:
mono_mb_emit_ldloc (mb, 1);
mono_mb_emit_ldloc (mb, 0);
- if (ntype == MONO_NATIVE_U1) {
+ if (t == MONO_TYPE_CHAR && ntype == MONO_NATIVE_U1 && string_encoding != MONO_NATIVE_LPWSTR) {
if (to_object) {
mono_mb_emit_byte (mb, CEE_LDIND_U1);
mono_mb_emit_byte (mb, CEE_STIND_I2);
}
}
+static void
+emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object)
+{
+ emit_struct_conv_full (mb, klass, to_object, -1);
+}
+
static void
emit_struct_free (MonoMethodBuilder *mb, MonoClass *klass, int struct_var)
{
res = newm;
new_key = g_new0 (SignatureMethodPair, 1);
*new_key = key;
+ if (static_method_with_first_arg_bound)
+ new_key->sig = signature_dup (del->method->klass->image, key.sig);
g_hash_table_insert (cache, new_key, res);
mono_marshal_set_wrapper_info (res, new_key);
mono_marshal_unlock ();
csig->params [2] = &mono_defaults.int_class->byval_arg;
csig->params [3] = &mono_defaults.int_class->byval_arg;
csig->pinvoke = 1;
+#if TARGET_WIN32
+ /* This is called from runtime code so it has to be cdecl */
+ csig->call_convention = MONO_CALL_C;
+#endif
name = mono_signature_to_name (callsig, virtual ? "runtime_invoke_virtual" : "runtime_invoke");
mb = mono_mb_new (target_klass, name, MONO_WRAPPER_RUNTIME_INVOKE);
static MonoClass *ICustomMarshaler = NULL;
static MonoMethod *cleanup_native, *cleanup_managed;
static MonoMethod *marshal_managed_to_native, *marshal_native_to_managed;
- MonoMethod *get_instance;
+ MonoMethod *get_instance = NULL;
MonoMethodBuilder *mb = m->mb;
char *exception_msg = NULL;
guint32 loc1;
if (!ICustomMarshaler) {
ICustomMarshaler = mono_class_from_name (mono_defaults.corlib, "System.Runtime.InteropServices", "ICustomMarshaler");
- g_assert (ICustomMarshaler);
+ if (!ICustomMarshaler) {
+ exception_msg = g_strdup ("Current profile doesn't support ICustomMarshaler");
+ goto handle_exception;
+ }
cleanup_native = mono_class_get_method_from_name (ICustomMarshaler, "CleanUpNativeData", 1);
g_assert (cleanup_native);
if (!get_instance)
exception_msg = g_strdup_printf ("Custom marshaler '%s' does not implement a static GetInstance method that takes a single string parameter and returns an ICustomMarshaler.", mklass->name);
+handle_exception:
/* Throw exception and emit compensation code if neccesary */
if (exception_msg) {
switch (action) {
}
mono_mb_emit_ldloc (mb, conv_arg);
- mono_mb_emit_icall (mb, g_free);
+ mono_mb_emit_icall (mb, mono_marshal_free);
mono_mb_patch_branch (mb, pos2);
}
/* Free the pointer allocated by unmanaged code */
mono_mb_emit_ldloc (mb, loc);
- mono_mb_emit_icall (mb, g_free);
+ mono_mb_emit_icall (mb, mono_marshal_free);
mono_mb_patch_branch (mb, pos);
}
break;
mono_mb_emit_stloc (mb, 1);
/* emit valuetype conversion code */
- emit_struct_conv (mb, eklass, FALSE);
+ emit_struct_conv_full (mb, eklass, FALSE, eklass == mono_defaults.char_class ? encoding : -1);
}
mono_mb_emit_add_to_local (mb, index_var, 1);
mono_mb_emit_stloc (mb, 1);
/* emit valuetype conversion code */
- emit_struct_conv (mb, eklass, TRUE);
+ emit_struct_conv_full (mb, eklass, TRUE, eklass == mono_defaults.char_class ? encoding : -1);
}
if (need_free) {
res = mono_mb_create_method (mb, signature, 4);
res->flags |= METHOD_ATTRIBUTE_VIRTUAL;
mono_marshal_set_wrapper_info (res, GUINT_TO_POINTER (kind + 1));
- cached_methods [kind] = res;
+
+ mono_marshal_lock ();
+ if (!cached_methods [kind]) {
+ cached_methods [kind] = res;
+ mono_marshal_unlock ();
+ } else {
+ mono_marshal_unlock ();
+ mono_free_method (res);
+ }
mono_mb_free (mb);
- return res;
+ return cached_methods [kind];
}
MonoMethod*