Default to SAFEARRAY(VARIANT) as CCW argument for object[]. (mono/mono#16673)
authorNikolay Sivov <nsivov@codeweavers.com>
Mon, 9 Sep 2019 17:02:46 +0000 (20:02 +0300)
committerMarek Safar <marek.safar@gmail.com>
Mon, 9 Sep 2019 17:02:46 +0000 (19:02 +0200)
* [cominterop] Add a helper to create default marshal spec for ccw arguments.

* [cominterop] Default to SAFEARRAY(VARIANT) as CCW argument for object[].

* [cominterop] Fix build with --enable-cxx.

Commit migrated from https://github.com/mono/mono/commit/8590a25b301ec08ac688e93df37fe3ef3c2ddb11

src/mono/mono/metadata/cominterop.c
src/mono/mono/tests/cominterop.cs
src/mono/mono/tests/libtest.c

index 9396d4d..e656c65 100644 (file)
@@ -2017,6 +2017,46 @@ cominterop_setup_marshal_context (EmitMarshalContext *m, MonoMethod *method)
        m->csig = csig;
 }
 
+static MonoMarshalSpec*
+cominterop_get_ccw_default_mspec (const MonoType *param_type)
+{
+       MonoMarshalVariant elem_type;
+       MonoMarshalNative native;
+       MonoMarshalSpec *result;
+
+       switch (param_type->type) {
+       case MONO_TYPE_OBJECT:
+               native = MONO_NATIVE_STRUCT;
+               break;
+       case MONO_TYPE_STRING:
+               native = MONO_NATIVE_BSTR;
+               break;
+       case MONO_TYPE_CLASS:
+               native = MONO_NATIVE_INTERFACE;
+               break;
+       case MONO_TYPE_BOOLEAN:
+               native = MONO_NATIVE_VARIANTBOOL;
+               break;
+       case MONO_TYPE_SZARRAY:
+               /* object[] -> SAFEARRAY(VARIANT) */
+               native = MONO_NATIVE_SAFEARRAY;
+               if (param_type->data.array->eklass == mono_defaults.object_class)
+                       elem_type = MONO_VARIANT_VARIANT;
+               else
+                       return NULL;
+               break;
+       default:
+               return NULL;
+       }
+
+       result = g_new0 (MonoMarshalSpec, 1);
+       result->native = native;
+       if (native == MONO_NATIVE_SAFEARRAY)
+               result->data.safearray_data.elem_type = elem_type;
+
+       return result;
+}
+
 /**
  * cominterop_get_ccw_checked:
  * @object: a pointer to the object
@@ -2159,22 +2199,7 @@ cominterop_get_ccw_checked (MonoObjectHandle object, MonoClass* itf, MonoError *
                                mspecs [mspec_index] = mspecs [param_index];
 
                                if (mspecs[mspec_index] == NULL) {
-                                       if (sig_adjusted->params[param_index]->type == MONO_TYPE_OBJECT) {
-                                               mspecs[mspec_index] = g_new0 (MonoMarshalSpec, 1);
-                                               mspecs[mspec_index]->native = MONO_NATIVE_STRUCT;
-                                       }
-                                       else if (sig_adjusted->params[param_index]->type == MONO_TYPE_STRING) {
-                                               mspecs[mspec_index] = g_new0 (MonoMarshalSpec, 1);
-                                               mspecs[mspec_index]->native = MONO_NATIVE_BSTR;
-                                       }
-                                       else if (sig_adjusted->params[param_index]->type == MONO_TYPE_CLASS) {
-                                               mspecs[mspec_index] = g_new0 (MonoMarshalSpec, 1);
-                                               mspecs[mspec_index]->native = MONO_NATIVE_INTERFACE;
-                                       }
-                                       else if (sig_adjusted->params[param_index]->type == MONO_TYPE_BOOLEAN) {
-                                               mspecs[mspec_index] = g_new0 (MonoMarshalSpec, 1);
-                                               mspecs[mspec_index]->native = MONO_NATIVE_VARIANTBOOL;
-                                       }
+                                       mspecs[mspec_index] = cominterop_get_ccw_default_mspec (sig_adjusted->params[param_index]);
                                } else {
                                        /* increase SizeParamIndex since we've added a param */
                                        if (sig_adjusted->params[param_index]->type == MONO_TYPE_ARRAY ||
@@ -2189,24 +2214,8 @@ cominterop_get_ccw_checked (MonoObjectHandle object, MonoClass* itf, MonoError *
 
                        /* move return spec to last param */
                        if (!preserve_sig && !MONO_TYPE_IS_VOID (sig->ret)) {
-                               if (mspecs [0] == NULL) {
-                                       if (sig_adjusted->params[sig_adjusted->param_count-1]->type == MONO_TYPE_OBJECT) {
-                                               mspecs[0] = g_new0 (MonoMarshalSpec, 1);
-                                               mspecs[0]->native = MONO_NATIVE_STRUCT;
-                                       }
-                                       else if (sig_adjusted->params[sig_adjusted->param_count-1]->type == MONO_TYPE_STRING) {
-                                               mspecs[0] = g_new0 (MonoMarshalSpec, 1);
-                                               mspecs[0]->native = MONO_NATIVE_BSTR;
-                                       }
-                                       else if (sig_adjusted->params[sig_adjusted->param_count-1]->type == MONO_TYPE_CLASS) {
-                                               mspecs[0] = g_new0 (MonoMarshalSpec, 1);
-                                               mspecs[0]->native = MONO_NATIVE_INTERFACE;
-                                       }
-                                       else if (sig_adjusted->params[sig_adjusted->param_count-1]->type == MONO_TYPE_BOOLEAN) {
-                                               mspecs[0] = g_new0 (MonoMarshalSpec, 1);
-                                               mspecs[0]->native = MONO_NATIVE_VARIANTBOOL;
-                                       }
-                               }
+                               if (mspecs [0] == NULL)
+                                       mspecs[0] = cominterop_get_ccw_default_mspec (sig_adjusted->params[sig_adjusted->param_count-1]);
 
                                mspecs [sig_adjusted->param_count] = mspecs [0];
                                mspecs [0] = NULL;
index d58a481..89ae03b 100644 (file)
@@ -880,6 +880,8 @@ public class Tests
                [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
                void ArrayIn ([In, MarshalAs (UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)] object[] array);
                [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+               void ArrayIn2 ([In] object[] array);
+               [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
                [return: MarshalAs (UnmanagedType.Interface)]
                TestDefaultInterfaceClass1 GetDefInterface1();
                [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
@@ -943,6 +945,8 @@ public class Tests
                int IntOut (out int val);
                [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
                int ArrayIn ([In, MarshalAs (UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)] object[] array);
+               [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+               int ArrayIn2 ([In] object[] array);
        }
 
        [System.Runtime.InteropServices.GuidAttribute ("00000000-0000-0000-0000-000000000002")]
@@ -989,6 +993,8 @@ public class Tests
                [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
                public virtual extern void ArrayIn ([In, MarshalAs (UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)] object[] array);
                [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+               public virtual extern void ArrayIn2 ([In] object[] array);
+               [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
                public virtual extern TestDefaultInterfaceClass1 GetDefInterface1();
                [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
                public virtual extern TestDefaultInterfaceClass2 GetDefInterface2();
@@ -1170,6 +1176,11 @@ public class Tests
 
                        return 444;
                }
+
+               public int ArrayIn2(object[] array)
+               {
+                       return ArrayIn(array);
+               }
        }
 
        public class ManagedTest : ITest
@@ -1294,6 +1305,11 @@ public class Tests
                        status = 444;
                }
 
+               public void ArrayIn2(object[] array)
+               {
+                       ArrayIn(array);
+               }
+
                public TestDefaultInterfaceClass1 GetDefInterface1()
                {
                        return new TestDefaultInterfaceClass1();
index d58413f..d5e9a9d 100644 (file)
@@ -3400,6 +3400,7 @@ typedef struct
        int (STDCALL *Return22NoICall)(MonoComObject* pUnk);
        int (STDCALL *IntOut)(MonoComObject* pUnk, int *a);
        int (STDCALL *ArrayIn)(MonoComObject* pUnk, void *array);
+       int (STDCALL *ArrayIn2)(MonoComObject* pUnk, void *array);
        int (STDCALL *GetDefInterface1)(MonoComObject* pUnk, MonoDefItfObject **iface);
        int (STDCALL *GetDefInterface2)(MonoComObject* pUnk, MonoDefItfObject **iface);
 } MonoIUnknown;
@@ -3543,6 +3544,12 @@ ArrayIn(MonoComObject* pUnk, void *array)
 }
 
 LIBTEST_API int STDCALL
+ArrayIn2(MonoComObject* pUnk, void *array)
+{
+       return S_OK;
+}
+
+LIBTEST_API int STDCALL
 GetDefInterface1(MonoComObject* pUnk, MonoDefItfObject **obj)
 {
        return S_OK;
@@ -3588,6 +3595,7 @@ static void create_com_object (MonoComObject** pOut)
        (*pOut)->vtbl->Return22NoICall = Return22NoICall;
        (*pOut)->vtbl->IntOut = IntOut;
        (*pOut)->vtbl->ArrayIn = ArrayIn;
+       (*pOut)->vtbl->ArrayIn2 = ArrayIn2;
        (*pOut)->vtbl->GetDefInterface1 = GetDefInterface1;
        (*pOut)->vtbl->GetDefInterface2 = GetDefInterface2;
 }
@@ -5647,6 +5655,8 @@ mono_test_marshal_safearray_in_ccw(MonoComObject *pUnk)
        SafeArrayPutElement(array, &index, &var);
 
        ret = pUnk->vtbl->ArrayIn (pUnk, (void *)array);
+       if (!ret)
+               ret = pUnk->vtbl->ArrayIn2 (pUnk, (void *)array);
 
        SafeArrayDestroy(array);