+2007-01-11 Jonathan Chambers <joncham@gmail.com>
+
+ * marshal.c (emit_marshal_variant): Handle unmanaged->managed
+ marshalling.
+ (mono_marshal_emit_managed_wrapper): Convert byref arguments of type
+ MONO_TYPE_OBJECT back for VARIANT support.
+
2007-01-11 Jonathan Chambers <joncham@gmail.com>
* marshal.c, marshal.h, icall-def.h: Implement
MarshalAction action)
{
MonoMethodBuilder *mb = m->mb;
+ static MonoMethod *get_object_for_native_variant = NULL;
+ static MonoMethod *get_native_variant_for_object = NULL;
+
+ if (!get_object_for_native_variant)
+ get_object_for_native_variant = mono_class_get_method_from_name (mono_defaults.marshal_class, "GetObjectForNativeVariant", 1);
+ g_assert (get_object_for_native_variant);
+
+ if (!get_native_variant_for_object)
+ get_native_variant_for_object = mono_class_get_method_from_name (mono_defaults.marshal_class, "GetNativeVariantForObject", 2);
+ g_assert (get_native_variant_for_object);
switch (action) {
case MARSHAL_ACTION_CONV_IN: {
- static MonoMethod *get_native_variant_for_object = NULL;
-
- if (!get_native_variant_for_object)
- get_native_variant_for_object = mono_class_get_method_from_name (mono_defaults.marshal_class, "GetNativeVariantForObject", 2);
- g_assert (get_native_variant_for_object);
-
*conv_arg_type = &mono_defaults.variant_class->byval_arg;
conv_arg = mono_mb_add_local (mb, &mono_defaults.variant_class->byval_arg);
+ if (t->byref && t->attrs & PARAM_ATTRIBUTE_OUT)
+ break;
+
mono_mb_emit_ldarg (mb, argnum);
if (t->byref)
mono_mb_emit_byte(mb, CEE_LDIND_REF);
case MARSHAL_ACTION_CONV_OUT: {
static MonoMethod *variant_clear = NULL;
- static MonoMethod *get_object_for_native_variant = NULL;
if (!variant_clear)
variant_clear = mono_class_get_method_from_name (mono_defaults.variant_class, "Clear", 0);
g_assert (variant_clear);
- if (!get_object_for_native_variant)
- get_object_for_native_variant = mono_class_get_method_from_name (mono_defaults.marshal_class, "GetObjectForNativeVariant", 1);
- g_assert (get_object_for_native_variant);
if (t->byref) {
mono_mb_emit_ldarg (mb, argnum);
break;
case MARSHAL_ACTION_CONV_RESULT: {
- char *msg = g_strdup ("Marshalling of VARIANT not supported.");
+ char *msg = g_strdup ("Marshalling of VARIANT not supported as a return type.");
mono_mb_emit_exception_marshal_directive (mb, msg);
break;
}
case MARSHAL_ACTION_MANAGED_CONV_IN: {
- char *msg = g_strdup ("Marshalling of VARIANT not supported.");
- mono_mb_emit_exception_marshal_directive (mb, msg);
+ *conv_arg_type = &mono_defaults.variant_class->this_arg;
+ conv_arg = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
+
+ if (t->byref && t->attrs & PARAM_ATTRIBUTE_OUT)
+ break;
+
+ if (t->byref)
+ mono_mb_emit_ldarg (mb, argnum);
+ else
+ mono_mb_emit_ldarg_addr (mb, argnum);
+ mono_mb_emit_managed_call (mb, get_object_for_native_variant, NULL);
+ mono_mb_emit_stloc (mb, conv_arg);
break;
}
case MARSHAL_ACTION_MANAGED_CONV_OUT: {
- char *msg = g_strdup ("Marshalling of VARIANT not supported.");
- mono_mb_emit_exception_marshal_directive (mb, msg);
+ if (t->byref) {
+ mono_mb_emit_ldloc (mb, conv_arg);
+ mono_mb_emit_ldarg (mb, argnum);
+ mono_mb_emit_managed_call (mb, get_native_variant_for_object, NULL);
+ }
break;
}
case MARSHAL_ACTION_MANAGED_CONV_RESULT: {
- char *msg = g_strdup ("Marshalling of VARIANT not supported.");
+ char *msg = g_strdup ("Marshalling of VARIANT not supported as a return type.");
mono_mb_emit_exception_marshal_directive (mb, msg);
break;
}
switch (t->type) {
case MONO_TYPE_CLASS:
case MONO_TYPE_VALUETYPE:
+ case MONO_TYPE_OBJECT:
emit_marshal (m, i, t, mspecs [i + 1], tmp_locals [i], NULL, MARSHAL_ACTION_MANAGED_CONV_OUT);
break;
}
+2007-01-11 Jonathan Chambers <joncham@gmail.com>
+
+ * libtest.c, cominterop.cs: Tests for unmanaged->managed
+ VARIANT marshalling.
+
2007-01-10 Robert Jordan <robertj@gmx.net>
* bug-80392.2.cs: Add more tests.
[DllImport ("libtest")]
public static extern int mono_test_marshal_variant_out_bool_false ([MarshalAs (UnmanagedType.Struct)]out object obj);
+
+ public delegate int VarFunc (VarEnum vt, [MarshalAs (UnmanagedType.Struct)] object obj);
+
+ public delegate int VarRefFunc (VarEnum vt, [MarshalAs (UnmanagedType.Struct)] ref object obj);
+
+ [DllImport ("libtest")]
+ public static extern int mono_test_marshal_variant_in_sbyte_unmanaged (VarFunc func);
+
+ [DllImport ("libtest")]
+ public static extern int mono_test_marshal_variant_in_byte_unmanaged (VarFunc func);
+
+ [DllImport ("libtest")]
+ public static extern int mono_test_marshal_variant_in_short_unmanaged (VarFunc func);
+
+ [DllImport ("libtest")]
+ public static extern int mono_test_marshal_variant_in_ushort_unmanaged (VarFunc func);
+
+ [DllImport ("libtest")]
+ public static extern int mono_test_marshal_variant_in_int_unmanaged (VarFunc func);
+
+ [DllImport ("libtest")]
+ public static extern int mono_test_marshal_variant_in_uint_unmanaged (VarFunc func);
+
+ [DllImport ("libtest")]
+ public static extern int mono_test_marshal_variant_in_long_unmanaged (VarFunc func);
+
+ [DllImport ("libtest")]
+ public static extern int mono_test_marshal_variant_in_ulong_unmanaged (VarFunc func);
+
+ [DllImport ("libtest")]
+ public static extern int mono_test_marshal_variant_in_float_unmanaged (VarFunc func);
+
+ [DllImport ("libtest")]
+ public static extern int mono_test_marshal_variant_in_double_unmanaged (VarFunc func);
+
+ [DllImport ("libtest")]
+ public static extern int mono_test_marshal_variant_in_bstr_unmanaged (VarFunc func);
+
+ [DllImport ("libtest")]
+ public static extern int mono_test_marshal_variant_in_bool_true_unmanaged (VarFunc func);
+
+ [DllImport ("libtest")]
+ public static extern int mono_test_marshal_variant_in_bool_false_unmanaged (VarFunc func);
+
+ [DllImport ("libtest")]
+ public static extern int mono_test_marshal_variant_out_sbyte_unmanaged (VarRefFunc func);
+
+ [DllImport ("libtest")]
+ public static extern int mono_test_marshal_variant_out_byte_unmanaged (VarRefFunc func);
+
+ [DllImport ("libtest")]
+ public static extern int mono_test_marshal_variant_out_short_unmanaged (VarRefFunc func);
+
+ [DllImport ("libtest")]
+ public static extern int mono_test_marshal_variant_out_ushort_unmanaged (VarRefFunc func);
+
+ [DllImport ("libtest")]
+ public static extern int mono_test_marshal_variant_out_int_unmanaged (VarRefFunc func);
+
+ [DllImport ("libtest")]
+ public static extern int mono_test_marshal_variant_out_uint_unmanaged (VarRefFunc func);
+
+ [DllImport ("libtest")]
+ public static extern int mono_test_marshal_variant_out_long_unmanaged (VarRefFunc func);
+
+ [DllImport ("libtest")]
+ public static extern int mono_test_marshal_variant_out_ulong_unmanaged (VarRefFunc func);
+
+ [DllImport ("libtest")]
+ public static extern int mono_test_marshal_variant_out_float_unmanaged (VarRefFunc func);
+
+ [DllImport ("libtest")]
+ public static extern int mono_test_marshal_variant_out_double_unmanaged (VarRefFunc func);
+
+ [DllImport ("libtest")]
+ public static extern int mono_test_marshal_variant_out_bstr_unmanaged (VarRefFunc func);
+
+ [DllImport ("libtest")]
+ public static extern int mono_test_marshal_variant_out_bool_true_unmanaged (VarRefFunc func);
+
+ [DllImport ("libtest")]
+ public static extern int mono_test_marshal_variant_out_bool_false_unmanaged (VarRefFunc func);
+
+
[DllImport ("libtest")]
public static extern int mono_test_marshal_com_object_create (out IntPtr pUnk);
if (mono_test_marshal_variant_out_bstr (out obj) != 0 || (string)obj != "PI")
return 34;
+ VarFunc func = new VarFunc (mono_test_marshal_variant_in_callback);
+ if (mono_test_marshal_variant_in_sbyte_unmanaged (func) != 0)
+ return 35;
+ if (mono_test_marshal_variant_in_byte_unmanaged (func) != 0)
+ return 36;
+ if (mono_test_marshal_variant_in_short_unmanaged (func) != 0)
+ return 37;
+ if (mono_test_marshal_variant_in_ushort_unmanaged (func) != 0)
+ return 38;
+ if (mono_test_marshal_variant_in_int_unmanaged (func) != 0)
+ return 39;
+ if (mono_test_marshal_variant_in_uint_unmanaged (func) != 0)
+ return 40;
+ if (mono_test_marshal_variant_in_long_unmanaged (func) != 0)
+ return 41;
+ if (mono_test_marshal_variant_in_ulong_unmanaged (func) != 0)
+ return 42;
+ if (mono_test_marshal_variant_in_float_unmanaged (func) != 0)
+ return 43;
+ if (mono_test_marshal_variant_in_double_unmanaged (func) != 0)
+ return 44;
+ if (mono_test_marshal_variant_in_bstr_unmanaged (func) != 0)
+ return 45;
+ if (mono_test_marshal_variant_in_bool_true_unmanaged (func) != 0)
+ return 46;
+
+ VarRefFunc reffunc = new VarRefFunc (mono_test_marshal_variant_out_callback);
+ if (mono_test_marshal_variant_out_sbyte_unmanaged (reffunc) != 0)
+ return 50;
+ if (mono_test_marshal_variant_out_byte_unmanaged (reffunc) != 0)
+ return 51;
+ if (mono_test_marshal_variant_out_short_unmanaged (reffunc) != 0)
+ return 52;
+ if (mono_test_marshal_variant_out_ushort_unmanaged (reffunc) != 0)
+ return 53;
+ if (mono_test_marshal_variant_out_int_unmanaged (reffunc) != 0)
+ return 54;
+ if (mono_test_marshal_variant_out_uint_unmanaged (reffunc) != 0)
+ return 55;
+ if (mono_test_marshal_variant_out_long_unmanaged (reffunc) != 0)
+ return 56;
+ if (mono_test_marshal_variant_out_ulong_unmanaged (reffunc) != 0)
+ return 57;
+ if (mono_test_marshal_variant_out_float_unmanaged (reffunc) != 0)
+ return 58;
+ if (mono_test_marshal_variant_out_double_unmanaged (reffunc) != 0)
+ return 59;
+ if (mono_test_marshal_variant_out_bstr_unmanaged (reffunc) != 0)
+ return 60;
+ if (mono_test_marshal_variant_out_bool_true_unmanaged (reffunc) != 0)
+ return 61;
+
#endregion // VARIANT Tests
#region Marshal COM Interop Tests
[MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public extern int Different ([MarshalAs (UnmanagedType.Interface)] out IMath imath);
}
+
+ public static int mono_test_marshal_variant_in_callback (VarEnum vt, object obj)
+ {
+ switch (vt)
+ {
+ case VarEnum.VT_I1:
+ if (obj.GetType () != typeof (sbyte))
+ return 1;
+ if ((sbyte)obj != -100)
+ return 2;
+ break;
+ case VarEnum.VT_UI1:
+ if (obj.GetType () != typeof (byte))
+ return 1;
+ if ((byte)obj != 100)
+ return 2;
+ break;
+ case VarEnum.VT_I2:
+ if (obj.GetType () != typeof (short))
+ return 1;
+ if ((short)obj != -100)
+ return 2;
+ break;
+ case VarEnum.VT_UI2:
+ if (obj.GetType () != typeof (ushort))
+ return 1;
+ if ((ushort)obj != 100)
+ return 2;
+ break;
+ case VarEnum.VT_I4:
+ if (obj.GetType () != typeof (int))
+ return 1;
+ if ((int)obj != -100)
+ return 2;
+ break;
+ case VarEnum.VT_UI4:
+ if (obj.GetType () != typeof (uint))
+ return 1;
+ if ((uint)obj != 100)
+ return 2;
+ break;
+ case VarEnum.VT_I8:
+ if (obj.GetType () != typeof (long))
+ return 1;
+ if ((long)obj != -100)
+ return 2;
+ break;
+ case VarEnum.VT_UI8:
+ if (obj.GetType () != typeof (ulong))
+ return 1;
+ if ((ulong)obj != 100)
+ return 2;
+ break;
+ case VarEnum.VT_R4:
+ if (obj.GetType () != typeof (float))
+ return 1;
+ if (Math.Abs ((float)obj - 3.14f) > 1e-10)
+ return 2;
+ break;
+ case VarEnum.VT_R8:
+ if (obj.GetType () != typeof (double))
+ return 1;
+ if (Math.Abs ((double)obj - 3.14) > 1e-10)
+ return 2;
+ break;
+ case VarEnum.VT_BSTR:
+ if (obj.GetType () != typeof (string))
+ return 1;
+ if ((string)obj != "PI")
+ return 2;
+ break;
+ case VarEnum.VT_BOOL:
+ if (obj.GetType () != typeof (bool))
+ return 1;
+ if ((bool)obj != true)
+ return 2;
+ break;
+ }
+ return 0;
+ }
+
+
+ public static int mono_test_marshal_variant_out_callback (VarEnum vt, ref object obj)
+ {
+ switch (vt) {
+ case VarEnum.VT_I1:
+ obj = (sbyte)-100;
+ break;
+ case VarEnum.VT_UI1:
+ obj = (byte)100;
+ break;
+ case VarEnum.VT_I2:
+ obj = (short)-100;
+ break;
+ case VarEnum.VT_UI2:
+ obj = (ushort)100;
+ break;
+ case VarEnum.VT_I4:
+ obj = (int)-100;
+ break;
+ case VarEnum.VT_UI4:
+ obj = (uint)100;
+ break;
+ case VarEnum.VT_I8:
+ obj = (long)-100;
+ break;
+ case VarEnum.VT_UI8:
+ obj = (ulong)100;
+ break;
+ case VarEnum.VT_R4:
+ obj = (float)3.14f;
+ break;
+ case VarEnum.VT_R8:
+ obj = (double)3.14;
+ break;
+ case VarEnum.VT_BSTR:
+ obj = "PI";
+ break;
+ case VarEnum.VT_BOOL:
+ obj = true;
+ break;
+ }
+ return 0;
+ }
}
STDCALL int
mono_test_marshal_variant_in_bool_true (VARIANT variant)
{
- if (variant.vt == VT_BOOL && variant.ullVal == VARIANT_TRUE)
+ if (variant.vt == VT_BOOL && variant.boolVal == VARIANT_TRUE)
return 0;
return 1;
}
STDCALL int
mono_test_marshal_variant_in_bool_false (VARIANT variant)
{
- if (variant.vt == VT_BOOL && variant.ullVal == VARIANT_FALSE)
+ if (variant.vt == VT_BOOL && variant.boolVal == VARIANT_FALSE)
return 0;
return 1;
}
mono_test_marshal_variant_out_bool_true (VARIANT* variant)
{
variant->vt = VT_BOOL;
- variant->bstrVal = VARIANT_TRUE;
+ variant->boolVal = VARIANT_TRUE;
return 0;
}
mono_test_marshal_variant_out_bool_false (VARIANT* variant)
{
variant->vt = VT_BOOL;
- variant->bstrVal = VARIANT_FALSE;
+ variant->boolVal = VARIANT_FALSE;
return 0;
}
+typedef int (STDCALL *VarFunc) (int vt, VARIANT variant);
+typedef int (STDCALL *VarRefFunc) (int vt, VARIANT* variant);
+
+STDCALL int
+mono_test_marshal_variant_in_sbyte_unmanaged(VarFunc func)
+{
+ VARIANT vt;
+ vt.vt = VT_I1;
+ vt.cVal = -100;
+ return func (VT_I1, vt);
+}
+
+STDCALL int
+mono_test_marshal_variant_in_byte_unmanaged(VarFunc func)
+{
+ VARIANT vt;
+ vt.vt = VT_UI1;
+ vt.bVal = 100;
+ return func (VT_UI1, vt);
+}
+
+STDCALL int
+mono_test_marshal_variant_in_short_unmanaged(VarFunc func)
+{
+ VARIANT vt;
+ vt.vt = VT_I2;
+ vt.iVal = -100;
+ return func (VT_I2, vt);
+}
+
+STDCALL int
+mono_test_marshal_variant_in_ushort_unmanaged(VarFunc func)
+{
+ VARIANT vt;
+ vt.vt = VT_UI2;
+ vt.uiVal = 100;
+ return func (VT_UI2, vt);
+}
+
+STDCALL int
+mono_test_marshal_variant_in_int_unmanaged(VarFunc func)
+{
+ VARIANT vt;
+ vt.vt = VT_I4;
+ vt.lVal = -100;
+ return func (VT_I4, vt);
+}
+
+STDCALL int
+mono_test_marshal_variant_in_uint_unmanaged(VarFunc func)
+{
+ VARIANT vt;
+ vt.vt = VT_UI4;
+ vt.ulVal = 100;
+ return func (VT_UI4, vt);
+}
+
+STDCALL int
+mono_test_marshal_variant_in_long_unmanaged(VarFunc func)
+{
+ VARIANT vt;
+ vt.vt = VT_I8;
+ vt.llVal = -100;
+ return func (VT_I8, vt);
+}
+
+STDCALL int
+mono_test_marshal_variant_in_ulong_unmanaged(VarFunc func)
+{
+ VARIANT vt;
+ vt.vt = VT_UI8;
+ vt.ullVal = 100;
+ return func (VT_UI8, vt);
+}
+
+STDCALL int
+mono_test_marshal_variant_in_float_unmanaged(VarFunc func)
+{
+ VARIANT vt;
+ vt.vt = VT_R4;
+ vt.fltVal = 3.14;
+ return func (VT_R4, vt);
+}
+
+STDCALL int
+mono_test_marshal_variant_in_double_unmanaged(VarFunc func)
+{
+ VARIANT vt;
+ vt.vt = VT_R8;
+ vt.dblVal = 3.14;
+ return func (VT_R8, vt);
+}
+
+STDCALL int
+mono_test_marshal_variant_in_bstr_unmanaged(VarFunc func)
+{
+ VARIANT vt;
+ vt.vt = VT_BSTR;
+ vt.bstrVal = SysAllocString(L"PI");
+ return func (VT_BSTR, vt);
+}
+
+STDCALL int
+mono_test_marshal_variant_in_bool_true_unmanaged(VarFunc func)
+{
+ VARIANT vt;
+ vt.vt = VT_BOOL;
+ vt.boolVal = VARIANT_TRUE;
+ return func (VT_BOOL, vt);
+}
+
+STDCALL int
+mono_test_marshal_variant_in_bool_false_unmanaged(VarFunc func)
+{
+ VARIANT vt;
+ vt.vt = VT_BOOL;
+ vt.boolVal = VARIANT_FALSE;
+ return func (VT_BOOL, vt);
+}
+
+STDCALL int
+mono_test_marshal_variant_out_sbyte_unmanaged(VarRefFunc func)
+{
+ VARIANT vt;
+ VariantInit (&vt);
+ func (VT_I1, &vt);
+ if (vt.vt == VT_I1 && vt.cVal == -100)
+ return 0;
+ return 1;
+}
+
+STDCALL int
+mono_test_marshal_variant_out_byte_unmanaged(VarRefFunc func)
+{
+ VARIANT vt;
+ VariantInit (&vt);
+ func (VT_UI1, &vt);
+ if (vt.vt == VT_UI1 && vt.bVal == 100)
+ return 0;
+ return 1;
+}
+
+STDCALL int
+mono_test_marshal_variant_out_short_unmanaged(VarRefFunc func)
+{
+ VARIANT vt;
+ VariantInit (&vt);
+ func (VT_I2, &vt);
+ if (vt.vt == VT_I2 && vt.iVal == -100)
+ return 0;
+ return 1;
+}
+
+STDCALL int
+mono_test_marshal_variant_out_ushort_unmanaged(VarRefFunc func)
+{
+ VARIANT vt;
+ VariantInit (&vt);
+ func (VT_UI2, &vt);
+ if (vt.vt == VT_UI2 && vt.uiVal == 100)
+ return 0;
+ return 1;
+}
+
+STDCALL int
+mono_test_marshal_variant_out_int_unmanaged(VarRefFunc func)
+{
+ VARIANT vt;
+ VariantInit (&vt);
+ func (VT_I4, &vt);
+ if (vt.vt == VT_I4 && vt.lVal == -100)
+ return 0;
+ return 1;
+}
+
+STDCALL int
+mono_test_marshal_variant_out_uint_unmanaged(VarRefFunc func)
+{
+ VARIANT vt;
+ VariantInit (&vt);
+ func (VT_UI4, &vt);
+ if (vt.vt == VT_UI4 && vt.ulVal == 100)
+ return 0;
+ return 1;
+}
+
+STDCALL int
+mono_test_marshal_variant_out_long_unmanaged(VarRefFunc func)
+{
+ VARIANT vt;
+ VariantInit (&vt);
+ func (VT_I8, &vt);
+ if (vt.vt == VT_I8 && vt.llVal == -100)
+ return 0;
+ return 1;
+}
+
+STDCALL int
+mono_test_marshal_variant_out_ulong_unmanaged(VarRefFunc func)
+{
+ VARIANT vt;
+ VariantInit (&vt);
+ func (VT_UI8, &vt);
+ if (vt.vt == VT_UI8 && vt.ullVal == 100)
+ return 0;
+ return 1;
+}
+
+STDCALL int
+mono_test_marshal_variant_out_float_unmanaged(VarRefFunc func)
+{
+ VARIANT vt;
+ VariantInit (&vt);
+ func (VT_R4, &vt);
+ if (vt.vt == VT_R4 && fabs (vt.fltVal - 3.14f) < 1e-10)
+ return 0;
+ return 1;
+}
+
+STDCALL int
+mono_test_marshal_variant_out_double_unmanaged(VarRefFunc func)
+{
+ VARIANT vt;
+ VariantInit (&vt);
+ func (VT_R8, &vt);
+ if (vt.vt == VT_R8 && fabs (vt.dblVal - 3.14) < 1e-10)
+ return 0;
+ return 1;
+}
+
+STDCALL int
+mono_test_marshal_variant_out_bstr_unmanaged(VarRefFunc func)
+{
+ VARIANT vt;
+ VariantInit (&vt);
+ func (VT_BSTR, &vt);
+ if (vt.vt == VT_BSTR && !wcscmp(vt.bstrVal, L"PI"))
+ return 0;
+ return 1;
+}
+
+STDCALL int
+mono_test_marshal_variant_out_bool_true_unmanaged(VarRefFunc func)
+{
+ VARIANT vt;
+ VariantInit (&vt);
+ func (VT_BOOL, &vt);
+ if (vt.vt == VT_BOOL && vt.boolVal == VARIANT_TRUE)
+ return 0;
+ return 1;
+}
+
+STDCALL int
+mono_test_marshal_variant_out_bool_false_unmanaged(VarRefFunc func)
+{
+ VARIANT vt;
+ VariantInit (&vt);
+ func (VT_BOOL, &vt);
+ if (vt.vt == VT_BOOL && vt.boolVal == VARIANT_TRUE)
+ return 0;
+ return 1;
+}
+
#ifdef _MSC_VER
#define COM_STDCALL __stdcall
#else