MonoMarshalSpec **mspecs;
MonoMethodSignature *sig, *sig_native;
MonoExceptionClause *main_clause = NULL;
+ int hr = 0, retval = 0;
int pos_leave;
- int hr = 0;
int i;
gboolean const preserve_sig = (method->iflags & METHOD_IMPL_ATTRIBUTE_PRESERVE_SIG) != 0;
mspecs [0] = NULL;
#ifndef DISABLE_JIT
- if (!preserve_sig)
+ if (!preserve_sig) {
+ if (!MONO_TYPE_IS_VOID (sig->ret))
+ retval = mono_mb_add_local (mb, sig->ret);
hr = mono_mb_add_local (mb, mono_get_int32_type ());
+ }
else if (!MONO_TYPE_IS_VOID (sig->ret))
hr = mono_mb_add_local (mb, sig->ret);
main_clause = g_new0 (MonoExceptionClause, 1);
main_clause->try_offset = mono_mb_get_label (mb);
- /* load last param to store result if not preserve_sig and not void */
- if (!preserve_sig && !MONO_TYPE_IS_VOID (sig->ret))
- mono_mb_emit_ldarg (mb, sig_native->param_count-1);
-
/* the CCW -> object conversion */
mono_mb_emit_ldarg (mb, 0);
mono_mb_emit_icon (mb, FALSE);
if (!MONO_TYPE_IS_VOID (sig->ret)) {
if (!preserve_sig) {
+ mono_mb_emit_stloc (mb, retval);
+ mono_mb_emit_ldarg (mb, sig_native->param_count - 1);
+ const int pos_null = mono_mb_emit_branch (mb, CEE_BRFALSE);
+
+ mono_mb_emit_ldarg (mb, sig_native->param_count - 1);
+ mono_mb_emit_ldloc (mb, retval);
+
MonoClass *rclass = mono_class_from_mono_type_internal (sig->ret);
if (m_class_is_valuetype (rclass)) {
mono_mb_emit_op (mb, CEE_STOBJ, rclass);
} else {
mono_mb_emit_byte (mb, mono_type_to_stind (sig->ret));
}
+
+ mono_mb_patch_branch (mb, pos_null);
} else
mono_mb_emit_stloc (mb, hr);
}
[DllImport ("libtest")]
public static extern int mono_test_marshal_array_ccw_itest (int count, [MarshalAs (UnmanagedType.LPArray, SizeParamIndex=0)] ITest[] ppUnk);
+ [DllImport ("libtest")]
+ public static extern int mono_test_marshal_retval_ccw_itest ([MarshalAs (UnmanagedType.Interface)]ITest itest, bool test_null);
+
+ [DllImport ("libtest")]
+ public static extern int mono_test_marshal_retval_ccw_itest ([MarshalAs (UnmanagedType.Interface)]ITestPresSig itest, bool test_null);
+
[DllImport("libtest")]
public static extern int mono_test_cominterop_ccw_queryinterface ([MarshalAs (UnmanagedType.Interface)] IOtherTest itest);
if (mono_test_cominterop_ccw_queryinterface (otherTest) != 0)
return 202;
+ if (mono_test_marshal_retval_ccw_itest(test, true) != 0)
+ return 203;
+
+ /* Passing NULL to an out parameter will crash. */
+ if (mono_test_marshal_retval_ccw_itest(test_pres_sig, false) != 0)
+ return 204;
+
#endregion // COM Callable Wrapper Tests
#region SAFEARRAY tests
[MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void ITestOut ([MarshalAs (UnmanagedType.Interface)]out ITest val);
int Return22NoICall();
+ [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ int IntOut();
}
[ComImport ()]
int ITestOut ([MarshalAs (UnmanagedType.Interface)]out ITestPresSig val);
[PreserveSig ()]
int Return22NoICall();
+ [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ [PreserveSig ()]
+ int IntOut (out int val);
}
[System.Runtime.InteropServices.GuidAttribute ("00000000-0000-0000-0000-000000000002")]
public virtual extern void ITestIn ([MarshalAs (UnmanagedType.Interface)]ITest val);
[MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void ITestOut ([MarshalAs (UnmanagedType.Interface)]out ITest val);
-
[MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern int Return22NoICall();
+ [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern int IntOut();
}
[System.Runtime.InteropServices.GuidAttribute ("00000000-0000-0000-0000-000000000002")]
{
return 88;
}
+
+ public int IntOut(out int val)
+ {
+ val = 33;
+ return 0;
+ }
}
public class ManagedTest : ITest
{
return 99;
}
+
+ public int IntOut()
+ {
+ return 33;
+ }
}
[ComVisible (true)]
int (STDCALL *ITestIn)(MonoComObject* pUnk, MonoComObject* pUnk2);
int (STDCALL *ITestOut)(MonoComObject* pUnk, MonoComObject* *ppUnk);
int (STDCALL *Return22NoICall)(MonoComObject* pUnk);
+ int (STDCALL *IntOut)(MonoComObject* pUnk, int *a);
} MonoIUnknown;
struct MonoComObject
return 22;
}
+LIBTEST_API int STDCALL
+IntOut(MonoComObject* pUnk, int *a)
+{
+ return S_OK;
+}
static void create_com_object (MonoComObject** pOut);
(*pOut)->vtbl->ITestOut = ITestOut;
(*pOut)->vtbl->get_ITest = get_ITest;
(*pOut)->vtbl->Return22NoICall = Return22NoICall;
+ (*pOut)->vtbl->IntOut = IntOut;
}
static MonoComObject* same_object = NULL;
return 0;
}
+LIBTEST_API int STDCALL
+mono_test_marshal_retval_ccw_itest (MonoComObject *pUnk, int test_null)
+{
+ int hr = 0, i = 0;
+
+ if (!pUnk)
+ return 1;
+
+ hr = pUnk->vtbl->IntOut (pUnk, &i);
+ if (hr != 0)
+ return 2;
+ if (i != 33)
+ return 3;
+ if (test_null)
+ {
+ hr = pUnk->vtbl->IntOut (pUnk, NULL);
+ if (hr != 0)
+ return 4;
+ }
+
+ return 0;
+}
+
/*
* mono_method_get_unmanaged_thunk tests
*/