return res;
}
-
-/*
- * generates IL code to call managed methods from unmanaged code
- */
-MonoMethod *
-mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass, MonoObject *this)
+
+/* FIXME: moving GC */
+static void
+mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *invoke_sig, MonoMarshalSpec **mspecs, EmitMarshalContext* m, MonoMethod *method, MonoObject* this)
{
- static MonoClass *UnmanagedFunctionPointerAttribute;
- MonoMethodSignature *sig, *csig, *invoke_sig;
- MonoMethodBuilder *mb;
- MonoMethod *res, *invoke;
- MonoMarshalSpec **mspecs;
- MonoMethodPInvoke piinfo;
- GHashTable *cache;
+ MonoMethodSignature *sig, *csig;
int i, *tmp_locals;
- EmitMarshalContext m;
- g_assert (method != NULL);
- g_assert (!mono_method_signature (method)->pinvoke);
-
- /*
- * FIXME: Should cache the method+delegate type pair, since the same method
- * could be called with different delegates, thus different marshalling
- * options.
- */
- cache = method->klass->image->managed_wrapper_cache;
- if (!this && (res = mono_marshal_find_in_cache (cache, method)))
- return res;
-
- invoke = mono_class_get_method_from_name (delegate_klass, "Invoke", mono_method_signature (method)->param_count);
- invoke_sig = mono_method_signature (invoke);
-
- mspecs = g_new0 (MonoMarshalSpec*, mono_method_signature (invoke)->param_count + 1);
- mono_method_get_marshal_info (invoke, mspecs);
-
- sig = mono_method_signature (method);
-
- mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_NATIVE_TO_MANAGED);
+ sig = m->sig;
+ csig = m->csig;
/* allocate local 0 (pointer) src_ptr */
mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
mono_mb_emit_icon (mb, 0);
mono_mb_emit_stloc (mb, 2);
- /* we copy the signature, so that we can modify it */
- csig = signature_dup (method->klass->image, sig);
- csig->hasthis = 0;
- csig->pinvoke = 1;
-
- m.mb = mb;
- m.sig = sig;
- m.piinfo = NULL;
- m.retobj_var = 0;
- m.csig = csig;
- m.image = method->klass->image;
-
-#ifdef PLATFORM_WIN32
- /*
- * Under windows, delegates passed to native code must use the STDCALL
- * calling convention.
- */
- csig->call_convention = MONO_CALL_STDCALL;
-#endif
-
- /* Change default calling convention if needed */
- /* Why is this a modopt ? */
- if (invoke_sig->ret && invoke_sig->ret->num_mods) {
- for (i = 0; i < invoke_sig->ret->num_mods; ++i) {
- MonoClass *cmod_class = mono_class_get (delegate_klass->image, invoke_sig->ret->modifiers [i].token);
- g_assert (cmod_class);
- if ((cmod_class->image == mono_defaults.corlib) && !strcmp (cmod_class->name_space, "System.Runtime.CompilerServices")) {
- if (!strcmp (cmod_class->name, "CallConvCdecl"))
- csig->call_convention = MONO_CALL_C;
- else if (!strcmp (cmod_class->name, "CallConvStdcall"))
- csig->call_convention = MONO_CALL_STDCALL;
- else if (!strcmp (cmod_class->name, "CallConvFastcall"))
- csig->call_convention = MONO_CALL_FASTCALL;
- else if (!strcmp (cmod_class->name, "CallConvThiscall"))
- csig->call_convention = MONO_CALL_THISCALL;
- }
- }
- }
-
- /* Handle the UnmanagedFunctionPointerAttribute */
- if (!UnmanagedFunctionPointerAttribute)
- UnmanagedFunctionPointerAttribute = mono_class_from_name (mono_defaults.corlib, "System.Runtime.InteropServices", "UnmanagedFunctionPointerAttribute");
-
- /* The attribute is only available in Net 2.0 */
- if (UnmanagedFunctionPointerAttribute) {
- MonoReflectionUnmanagedFunctionPointerAttribute *attr;
- MonoCustomAttrInfo *cinfo;
-
- /*
- * The pinvoke attributes are stored in a real custom attribute so we have to
- * construct it.
- */
- cinfo = mono_custom_attrs_from_class (delegate_klass);
- if (cinfo) {
- attr = (MonoReflectionUnmanagedFunctionPointerAttribute*)mono_custom_attrs_get_attr (cinfo, UnmanagedFunctionPointerAttribute);
- if (attr) {
- memset (&piinfo, 0, sizeof (piinfo));
- m.piinfo = &piinfo;
- piinfo.piflags = (attr->call_conv << 8) | (attr->charset ? (attr->charset - 1) * 2 : 1) | attr->set_last_error;
-
- csig->call_convention = attr->call_conv - 1;
- }
- if (!cinfo->cached)
- mono_custom_attrs_free (cinfo);
- }
- }
-
/* fixme: howto handle this ? */
if (sig->hasthis) {
if (this) {
case MONO_TYPE_ARRAY:
case MONO_TYPE_SZARRAY:
case MONO_TYPE_STRING:
- tmp_locals [i] = emit_marshal (&m, i, sig->params [i], mspecs [i + 1], 0, &csig->params [i], MARSHAL_ACTION_MANAGED_CONV_IN);
+ tmp_locals [i] = emit_marshal (m, i, sig->params [i], mspecs [i + 1], 0, &csig->params [i], MARSHAL_ACTION_MANAGED_CONV_IN);
break;
default:
mono_mb_emit_managed_call (mb, method, NULL);
if (mspecs [0] && mspecs [0]->native == MONO_NATIVE_CUSTOM) {
- emit_marshal (&m, 0, sig->ret, mspecs [0], 0, NULL, MARSHAL_ACTION_MANAGED_CONV_RESULT);
+ emit_marshal (m, 0, sig->ret, mspecs [0], 0, NULL, MARSHAL_ACTION_MANAGED_CONV_RESULT);
}
else
if (!sig->ret->byref) {
break;
case MONO_TYPE_STRING:
csig->ret = &mono_defaults.int_class->byval_arg;
- emit_marshal (&m, 0, sig->ret, mspecs [0], 0, NULL, MARSHAL_ACTION_MANAGED_CONV_RESULT);
+ emit_marshal (m, 0, sig->ret, mspecs [0], 0, NULL, MARSHAL_ACTION_MANAGED_CONV_RESULT);
break;
case MONO_TYPE_VALUETYPE:
case MONO_TYPE_CLASS:
case MONO_TYPE_SZARRAY:
- emit_marshal (&m, 0, sig->ret, mspecs [0], 0, NULL, MARSHAL_ACTION_MANAGED_CONV_RESULT);
+ emit_marshal (m, 0, sig->ret, mspecs [0], 0, NULL, MARSHAL_ACTION_MANAGED_CONV_RESULT);
break;
default:
g_warning ("return type 0x%02x unknown", sig->ret->type);
MonoMarshalSpec *spec = mspecs [i + 1];
if (spec && spec->native == MONO_NATIVE_CUSTOM) {
- emit_marshal (&m, i, t, mspecs [i + 1], tmp_locals [i], NULL, MARSHAL_ACTION_MANAGED_CONV_OUT);
+ emit_marshal (m, i, t, mspecs [i + 1], tmp_locals [i], NULL, MARSHAL_ACTION_MANAGED_CONV_OUT);
}
else if (t->byref) {
switch (t->type) {
case MONO_TYPE_CLASS:
case MONO_TYPE_VALUETYPE:
- emit_marshal (&m, i, t, mspecs [i + 1], tmp_locals [i], NULL, MARSHAL_ACTION_MANAGED_CONV_OUT);
+ emit_marshal (m, i, t, mspecs [i + 1], tmp_locals [i], NULL, MARSHAL_ACTION_MANAGED_CONV_OUT);
break;
}
}
case MONO_TYPE_SZARRAY:
case MONO_TYPE_CLASS:
case MONO_TYPE_VALUETYPE:
- emit_marshal (&m, i, invoke_sig->params [i], mspecs [i + 1], tmp_locals [i], NULL, MARSHAL_ACTION_MANAGED_CONV_OUT);
+ emit_marshal (m, i, invoke_sig->params [i], mspecs [i + 1], tmp_locals [i], NULL, MARSHAL_ACTION_MANAGED_CONV_OUT);
break;
default:
g_assert_not_reached ();
}
}
- if (m.retobj_var) {
- mono_mb_emit_ldloc (mb, m.retobj_var);
+ if (m->retobj_var) {
+ mono_mb_emit_ldloc (mb, m->retobj_var);
mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
- mono_mb_emit_op (mb, CEE_MONO_RETOBJ, m.retobj_class);
+ mono_mb_emit_op (mb, CEE_MONO_RETOBJ, m->retobj_class);
}
else {
if (!MONO_TYPE_IS_VOID(sig->ret))
mono_mb_emit_ldloc (mb, 3);
mono_mb_emit_byte (mb, CEE_RET);
}
+}
+
+
+/*
+ * generates IL code to call managed methods from unmanaged code
+ */
+MonoMethod *
+mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass, MonoObject *this)
+{
+ static MonoClass *UnmanagedFunctionPointerAttribute;
+ MonoMethodSignature *sig, *csig, *invoke_sig;
+ MonoMethodBuilder *mb;
+ MonoMethod *res, *invoke;
+ MonoMarshalSpec **mspecs;
+ MonoMethodPInvoke piinfo;
+ GHashTable *cache;
+ int i;
+ EmitMarshalContext m;
+
+ g_assert (method != NULL);
+ g_assert (!mono_method_signature (method)->pinvoke);
+
+ /*
+ * FIXME: Should cache the method+delegate type pair, since the same method
+ * could be called with different delegates, thus different marshalling
+ * options.
+ */
+ cache = method->klass->image->managed_wrapper_cache;
+ if (!this && (res = mono_marshal_find_in_cache (cache, method)))
+ return res;
+
+ invoke = mono_class_get_method_from_name (delegate_klass, "Invoke", mono_method_signature (method)->param_count);
+ invoke_sig = mono_method_signature (invoke);
+
+ mspecs = g_new0 (MonoMarshalSpec*, mono_method_signature (invoke)->param_count + 1);
+ mono_method_get_marshal_info (invoke, mspecs);
+
+ sig = mono_method_signature (method);
+
+ mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_NATIVE_TO_MANAGED);
+
+
+ /* we copy the signature, so that we can modify it */
+ csig = signature_dup (method->klass->image, sig);
+ csig->hasthis = 0;
+ csig->pinvoke = 1;
+
+ m.mb = mb;
+ m.sig = sig;
+ m.piinfo = NULL;
+ m.retobj_var = 0;
+ m.csig = csig;
+ m.image = method->klass->image;
+
+#ifdef PLATFORM_WIN32
+ /*
+ * Under windows, delegates passed to native code must use the STDCALL
+ * calling convention.
+ */
+ csig->call_convention = MONO_CALL_STDCALL;
+#endif
+
+ /* Change default calling convention if needed */
+ /* Why is this a modopt ? */
+ if (invoke_sig->ret && invoke_sig->ret->num_mods) {
+ for (i = 0; i < invoke_sig->ret->num_mods; ++i) {
+ MonoClass *cmod_class = mono_class_get (delegate_klass->image, invoke_sig->ret->modifiers [i].token);
+ g_assert (cmod_class);
+ if ((cmod_class->image == mono_defaults.corlib) && !strcmp (cmod_class->name_space, "System.Runtime.CompilerServices")) {
+ if (!strcmp (cmod_class->name, "CallConvCdecl"))
+ csig->call_convention = MONO_CALL_C;
+ else if (!strcmp (cmod_class->name, "CallConvStdcall"))
+ csig->call_convention = MONO_CALL_STDCALL;
+ else if (!strcmp (cmod_class->name, "CallConvFastcall"))
+ csig->call_convention = MONO_CALL_FASTCALL;
+ else if (!strcmp (cmod_class->name, "CallConvThiscall"))
+ csig->call_convention = MONO_CALL_THISCALL;
+ }
+ }
+ }
+
+ /* Handle the UnmanagedFunctionPointerAttribute */
+ if (!UnmanagedFunctionPointerAttribute)
+ UnmanagedFunctionPointerAttribute = mono_class_from_name (mono_defaults.corlib, "System.Runtime.InteropServices", "UnmanagedFunctionPointerAttribute");
+
+ /* The attribute is only available in Net 2.0 */
+ if (UnmanagedFunctionPointerAttribute) {
+ MonoReflectionUnmanagedFunctionPointerAttribute *attr;
+ MonoCustomAttrInfo *cinfo;
+
+ /*
+ * The pinvoke attributes are stored in a real custom attribute so we have to
+ * construct it.
+ */
+ cinfo = mono_custom_attrs_from_class (delegate_klass);
+ if (cinfo) {
+ attr = (MonoReflectionUnmanagedFunctionPointerAttribute*)mono_custom_attrs_get_attr (cinfo, UnmanagedFunctionPointerAttribute);
+ if (attr) {
+ memset (&piinfo, 0, sizeof (piinfo));
+ m.piinfo = &piinfo;
+ piinfo.piflags = (attr->call_conv << 8) | (attr->charset ? (attr->charset - 1) * 2 : 1) | attr->set_last_error;
+
+ csig->call_convention = attr->call_conv - 1;
+ }
+ if (!cinfo->cached)
+ mono_custom_attrs_free (cinfo);
+ }
+ }
+
+ mono_marshal_emit_managed_wrapper (mb, invoke_sig, mspecs, &m, method, this);
if (!this)
res = mono_mb_create_and_cache (cache, method,