2007-01-11 Jonathan Chambers <joncham@gmail.com>
authorJonathan Chambers <joncham@gmail.com>
Thu, 11 Jan 2007 20:06:20 +0000 (20:06 -0000)
committerJonathan Chambers <joncham@gmail.com>
Thu, 11 Jan 2007 20:06:20 +0000 (20:06 -0000)
* 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.

svn path=/trunk/mono/; revision=70881

mono/metadata/ChangeLog
mono/metadata/marshal.c
mono/tests/ChangeLog
mono/tests/cominterop.cs
mono/tests/libtest.c

index 74db8ebb8f7d8d09c68e9359d241322bddaacee3..cc5c80bf768e52831fdefef24f4a46011fe8aac0 100644 (file)
@@ -1,3 +1,10 @@
+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 
index 5d44c9b12d8439adf334447b3b8b921df8178b77..83ce990a09fbf4a1e6c1bea927af7d6496a72b97 100644 (file)
@@ -6789,18 +6789,25 @@ emit_marshal_variant (EmitMarshalContext *m, int argnum, MonoType *t,
                     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);
@@ -6811,15 +6818,11 @@ emit_marshal_variant (EmitMarshalContext *m, int argnum, MonoType *t,
 
        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);
@@ -6841,25 +6844,38 @@ emit_marshal_variant (EmitMarshalContext *m, int argnum, MonoType *t,
                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;
        }
@@ -8276,6 +8292,7 @@ mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *i
                        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;
                        }
index 68d419f05e300f770d00b8adc7c1bf421c39db4b..e91339cfcfbdc3cae7d604bc1b36f0e7488340a8 100644 (file)
@@ -1,3 +1,8 @@
+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.
index 7ca971ce9c0870c6e0ad51baec423728f698e526..d1f4f0f9ed5ee32244c4b0a96147e748ec66ba45 100644 (file)
@@ -101,6 +101,90 @@ public class 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);
 
@@ -177,6 +261,58 @@ public class Tests
                        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
@@ -297,4 +433,128 @@ public class 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;
+       }
 }
index 92fedf4853e65825539293e24f678d966692c513..e7aed156a17b5498b3a24149668630a016dfc970 100644 (file)
@@ -2127,7 +2127,7 @@ mono_test_marshal_variant_in_bstr(VARIANT variant)
 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;
 }
@@ -2135,7 +2135,7 @@ mono_test_marshal_variant_in_bool_true (VARIANT variant)
 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;
 }
@@ -2243,7 +2243,7 @@ STDCALL int
 mono_test_marshal_variant_out_bool_true (VARIANT* variant)
 {
        variant->vt = VT_BOOL;
-       variant->bstrVal = VARIANT_TRUE;
+       variant->boolVal = VARIANT_TRUE;
 
        return 0;
 }
@@ -2252,11 +2252,274 @@ STDCALL int
 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