diff --git a/src/mono/mono/metadata/metadata.c b/src/mono/mono/metadata/metadata.c index 056f2e6c45f90..8fd3fc856458a 100644 --- a/src/mono/mono/metadata/metadata.c +++ b/src/mono/mono/metadata/metadata.c @@ -7159,7 +7159,17 @@ mono_type_to_unmanaged (MonoType *type, MonoMarshalSpec *mspec, gboolean as_fiel if (mspec) { switch (mspec->native) { case MONO_NATIVE_STRUCT: - *conv = MONO_MARSHAL_CONV_OBJECT_STRUCT; + // [MarshalAs(UnmanagedType.Struct)] + // object field; + // + // becomes a VARIANT + // + // [MarshalAs(UnmangedType.Struct)] + // SomeClass field; + // + // becomes uses the CONV_OBJECT_STRUCT conversion + if (t != MONO_TYPE_OBJECT) + *conv = MONO_MARSHAL_CONV_OBJECT_STRUCT; return MONO_NATIVE_STRUCT; case MONO_NATIVE_CUSTOM: return MONO_NATIVE_CUSTOM; diff --git a/src/mono/mono/tests/cominterop.cs b/src/mono/mono/tests/cominterop.cs index 79ae06a34e63e..33c8e54be9ba4 100644 --- a/src/mono/mono/tests/cominterop.cs +++ b/src/mono/mono/tests/cominterop.cs @@ -224,7 +224,21 @@ public class Tests [DllImport ("libtest")] public static extern int mono_test_marshal_variant_out_bool_false_unmanaged (VarRefFunc func); - [DllImport ("libtest")] + public delegate int CheckStructWithVariantFunc ([MarshalAs (UnmanagedType.Struct)] StructWithVariant obj); + [DllImport ("libtest")] + public static extern int mono_test_marshal_struct_with_variant_in_unmanaged (CheckStructWithVariantFunc func); + + public delegate int CheckStructWithBstrFunc ([MarshalAs (UnmanagedType.Struct)] StructWithBstr obj); + [DllImport ("libtest")] + public static extern int mono_test_marshal_struct_with_bstr_in_unmanaged (CheckStructWithBstrFunc func); + + [DllImport ("libtest")] + public static extern int mono_test_marshal_struct_with_variant_out_unmanaged ([MarshalAs (UnmanagedType.Struct)] StructWithVariant obj); + + [DllImport ("libtest")] + public static extern int mono_test_marshal_struct_with_bstr_out_unmanaged ([MarshalAs (UnmanagedType.Struct)] StructWithBstr obj); + + [DllImport ("libtest")] public static extern int mono_test_marshal_com_object_create (out IntPtr pUnk); [DllImport ("libtest")] @@ -341,7 +355,6 @@ public static extern int mono_test_marshal_safearray_mixed ( public static int Main () { - bool isWindows = !(((int)Environment.OSVersion.Platform == 4) || ((int)Environment.OSVersion.Platform == 128)); @@ -359,6 +372,15 @@ public static int Main () if (mono_test_marshal_bstr_out_null (out str) != 0 || str != null) return 2; + var sbfunc = new CheckStructWithBstrFunc(mono_test_marshal_struct_with_bstr_callback); + if (mono_test_marshal_struct_with_bstr_in_unmanaged(sbfunc) != 0) + return 3; + + StructWithBstr swithB; + swithB.data = "this is a test string"; + if (mono_test_marshal_struct_with_bstr_out_unmanaged (swithB) != 0) + return 4; + #endregion // BSTR Tests #region VARIANT Tests @@ -484,6 +506,15 @@ public static int Main () if (mono_test_marshal_variant_out_bstr_byref (out obj) != 0 || (string)obj != "PI") return 107; + var svfunc = new CheckStructWithVariantFunc(mono_test_marshal_struct_with_variant_callback); + if (mono_test_marshal_struct_with_variant_in_unmanaged(svfunc) != 0) + return 108; + + StructWithVariant swithV; + swithV.data = (object)-123; + if (mono_test_marshal_struct_with_variant_out_unmanaged (swithV) != 0) + return 109; + #endregion // VARIANT Tests #region Runtime Callable Wrapper Tests @@ -1613,8 +1644,38 @@ public static int TestITestDelegate (ITest itest) public static int TestIfaceNoIcall (ITestPresSig itest) { return itest.Return22NoICall () == 22 ? 0 : 1; } + + public static int mono_test_marshal_struct_with_variant_callback(StructWithVariant sv) + { + if (sv.data.GetType() != typeof(int)) + return 1; + if ((int)sv.data != -123) + return 2; + return 0; + } + + public static int mono_test_marshal_struct_with_bstr_callback(StructWithBstr sb) + { + if (sb.data.GetType() != typeof(string)) + return 1; + if ((string)sb.data != "this is a test string") + return 2; + return 0; + } } public class TestVisible { } + +public struct StructWithVariant +{ + [MarshalAs (UnmanagedType.Struct)] + public object data; +} + +public struct StructWithBstr +{ + [MarshalAs (UnmanagedType.BStr)] + public string data; +} diff --git a/src/mono/mono/tests/libtest.c b/src/mono/mono/tests/libtest.c index 0f078a335ab9a..053d8678e30e0 100644 --- a/src/mono/mono/tests/libtest.c +++ b/src/mono/mono/tests/libtest.c @@ -3402,6 +3402,54 @@ mono_test_marshal_variant_out_bool_false_unmanaged(VarRefFunc func) return 1; } +typedef struct _StructWithVariant { + VARIANT data; +} StructWithVariant; +typedef int (STDCALL *CheckStructWithVariantFunc) (StructWithVariant sv); + +LIBTEST_API int STDCALL +mono_test_marshal_struct_with_variant_in_unmanaged(CheckStructWithVariantFunc func) +{ + StructWithVariant sv; + sv.data.vt = VT_I4; + sv.data.lVal = -123; + return func(sv); +} + +LIBTEST_API int STDCALL +mono_test_marshal_struct_with_variant_out_unmanaged (StructWithVariant sv) +{ + if (sv.data.vt != VT_I4) + return 1; + if (sv.data.lVal != -123) + return 2; + return 0; +} + +typedef struct _StructWithBstr { + gunichar2* data; +} StructWithBstr; +typedef int (STDCALL *CheckStructWithBstrFunc) (StructWithBstr sb); + +LIBTEST_API int STDCALL +mono_test_marshal_struct_with_bstr_in_unmanaged(CheckStructWithBstrFunc func) +{ + StructWithBstr sb; + sb.data = marshal_bstr_alloc("this is a test string"); + return func(sb); +} + +LIBTEST_API int STDCALL +mono_test_marshal_struct_with_bstr_out_unmanaged (StructWithBstr sb) +{ + char *s = g_utf16_to_utf8 (sb.data, g_utf16_len (sb.data), NULL, NULL, NULL); + gboolean same = !strcmp (s, "this is a test string"); + g_free (s); + if (!same) + return 1; + return 0; +} + typedef struct MonoComObject MonoComObject; typedef struct MonoDefItfObject MonoDefItfObject;