From 81bf071e053e213060990766acff4720dde9294c Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Mon, 9 Sep 2019 20:02:46 +0300 Subject: [PATCH] Default to SAFEARRAY(VARIANT) as CCW argument for object[]. (mono/mono#16673) * [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 | 77 +++++++++++++++++++++---------------- src/mono/mono/tests/cominterop.cs | 16 ++++++++ src/mono/mono/tests/libtest.c | 10 +++++ 3 files changed, 69 insertions(+), 34 deletions(-) diff --git a/src/mono/mono/metadata/cominterop.c b/src/mono/mono/metadata/cominterop.c index 9396d4d..e656c65 100644 --- a/src/mono/mono/metadata/cominterop.c +++ b/src/mono/mono/metadata/cominterop.c @@ -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; diff --git a/src/mono/mono/tests/cominterop.cs b/src/mono/mono/tests/cominterop.cs index d58a481..89ae03b 100644 --- a/src/mono/mono/tests/cominterop.cs +++ b/src/mono/mono/tests/cominterop.cs @@ -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(); diff --git a/src/mono/mono/tests/libtest.c b/src/mono/mono/tests/libtest.c index d58413f..d5e9a9d 100644 --- a/src/mono/mono/tests/libtest.c +++ b/src/mono/mono/tests/libtest.c @@ -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); -- 2.7.4