}
break;
}
+ case MARSHAL_ACTION_MANAGED_CONV_IN: {
+ if (!(t->attrs & PARAM_ATTRIBUTE_IN))
+ break;
+
+ /* Generates IL code for the following algorithm:
+
+ Array result; // result_var
+ IntPtr indices; // indices_var
+ int empty; // empty_var
+ if (mono_marshal_safearray_begin(safearray, out result, out indices, out empty, NULL, TRUE)) {
+ if (!empty) {
+ int index=0; // index_var
+ do { // label3
+ object elem = Variant.GetObjectForNativeVariant(mono_marshal_safearray_get_value(safearray, indices));
+ result.SetValueImpl(elem, index);
+ ++index;
+ }
+ while (mono_marshal_safearray_next(safearray, indices));
+ } // label2
+ mono_marshal_safearray_free_indices(indices);
+ } // label1
+ */
+
+ int result_var, indices_var, empty_var, elem_var, index_var;
+ guint32 label1 = 0, label2 = 0, label3 = 0;
+ static MonoMethod *get_object_for_native_variant = NULL;
+ static MonoMethod *set_value_impl = NULL;
+
+ MonoType *object_type = mono_get_object_type ();
+ MonoType *int_type = mono_get_int_type ();
+ result_var = mono_mb_add_local (mb, object_type);
+ indices_var = mono_mb_add_local (mb, int_type);
+ empty_var = mono_mb_add_local (mb, int_type);
+
+ mono_mb_emit_ldarg (mb, argnum);
+ mono_mb_emit_ldloc_addr (mb, result_var);
+ mono_mb_emit_ldloc_addr (mb, indices_var);
+ mono_mb_emit_ldloc_addr (mb, empty_var);
+ mono_mb_emit_byte (mb, CEE_LDC_I4_0);
+ mono_mb_emit_byte (mb, CEE_CONV_I);
+ mono_mb_emit_byte (mb, CEE_LDC_I4_1);
+ mono_mb_emit_icall (mb, mono_marshal_safearray_begin);
+
+ label1 = mono_mb_emit_short_branch (mb, CEE_BRFALSE_S);
+ mono_mb_emit_ldloc (mb, empty_var);
+
+ label2 = mono_mb_emit_short_branch (mb, CEE_BRTRUE_S);
+
+ index_var = mono_mb_add_local (mb, int_type);
+ mono_mb_emit_byte (mb, CEE_LDC_I4_0);
+ mono_mb_emit_stloc (mb, index_var);
+
+ label3 = mono_mb_get_label (mb);
+
+ mono_mb_emit_ldarg (mb, argnum);
+ mono_mb_emit_ldloc (mb, indices_var);
+ mono_mb_emit_icall (mb, mono_marshal_safearray_get_value);
+
+ if (!get_object_for_native_variant) {
+ ERROR_DECL (error);
+ get_object_for_native_variant = mono_class_get_method_from_name_checked (mono_defaults.marshal_class, "GetObjectForNativeVariant", 1, 0, error);
+ mono_error_assert_ok (error);
+ }
+ g_assert (get_object_for_native_variant);
+
+ if (!set_value_impl) {
+ ERROR_DECL (error);
+ set_value_impl = mono_class_get_method_from_name_checked (mono_defaults.array_class, "SetValueImpl", 2, 0, error);
+ mono_error_assert_ok (error);
+ }
+ g_assert (set_value_impl);
+
+ elem_var = mono_mb_add_local (mb, object_type);
+
+ mono_mb_emit_managed_call (mb, get_object_for_native_variant, NULL);
+ mono_mb_emit_stloc (mb, elem_var);
+
+ mono_mb_emit_ldloc (mb, result_var);
+ mono_mb_emit_ldloc (mb, elem_var);
+ mono_mb_emit_ldloc (mb, index_var);
+ mono_mb_emit_managed_call (mb, set_value_impl, NULL);
+
+ mono_mb_emit_add_to_local (mb, index_var, 1);
+
+ mono_mb_emit_ldarg (mb, argnum);
+ mono_mb_emit_ldloc (mb, indices_var);
+ mono_mb_emit_icall (mb, mono_marshal_safearray_next);
+ mono_mb_emit_branch_label (mb, CEE_BRTRUE, label3);
+
+ mono_mb_patch_short_branch (mb, label2);
+
+ mono_mb_emit_ldloc (mb, indices_var);
+ mono_mb_emit_icall (mb, mono_marshal_safearray_free_indices);
+
+ mono_mb_patch_short_branch (mb, label1);
+
+ mono_mb_emit_ldloc (mb, result_var);
+ mono_mb_emit_stloc (mb, conv_arg);
+
+ break;
+ }
default:
g_assert_not_reached ();
}
char *msg = g_strdup ("[MarshalAs] attribute required to marshal arrays to managed code.");
mono_mb_emit_exception_marshal_directive (mb, msg);
return conv_arg;
- }
- if (spec->native != MONO_NATIVE_LPARRAY) {
- char *msg = g_strdup ("Non LPArray marshalling of arrays to managed code is not implemented.");
+ }
+
+ switch (spec->native) {
+ case MONO_NATIVE_LPARRAY:
+ break;
+ case MONO_NATIVE_SAFEARRAY:
+#ifndef DISABLE_COM
+ if (spec->data.safearray_data.elem_type != MONO_VARIANT_VARIANT) {
+ char *msg = g_strdup ("Only SAFEARRAY(VARIANT) marshalling to managed code is implemented.");
+ mono_mb_emit_exception_marshal_directive (mb, msg);
+ return conv_arg;
+ }
+ return mono_cominterop_emit_marshal_safearray (m, argnum, t, spec, conv_arg, conv_arg_type, action);
+#endif
+ default: {
+ char *msg = g_strdup ("Unsupported array type marshalling to managed code.");
mono_mb_emit_exception_marshal_directive (mb, msg);
- return conv_arg;
+ return conv_arg;
+ }
}
/* FIXME: t is from the method which is wrapped, not the delegate type */
case MONO_TYPE_STRING:
case MONO_TYPE_BOOLEAN:
tmp_locals [i] = mono_emit_marshal (m, i, sig->params [i], mspecs [i + 1], 0, &csig->params [i], MARSHAL_ACTION_MANAGED_CONV_IN);
-
break;
default:
tmp_locals [i] = 0;
[In, Out, MarshalAs (UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)] ref Array array4);
[DllImport("libtest")]
+ public static extern int mono_test_marshal_safearray_in_ccw([MarshalAs (UnmanagedType.Interface)] ITest itest);
+
+ [DllImport("libtest")]
public static extern bool mono_cominterop_is_supported ();
public static int Main ()
if (isWindows) {
/* out */
-
Array array;
if ((mono_test_marshal_safearray_out_1dim_vt_bstr_empty (out array) != 0) || (array.Rank != 1) || (array.Length != 0))
return 62;
if (i != Convert.ToInt32 (array4.GetValue (i)))
return 96;
}
+ if (mono_test_marshal_safearray_in_ccw(test) != 0)
+ return 97;
}
#endregion // SafeArray Tests
int Return22NoICall();
[MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
int IntOut();
+ [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ void ArrayIn ([In, MarshalAs (UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)] object[] array);
}
[ComImport ()]
[MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
[PreserveSig ()]
int IntOut (out int val);
+ [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ int ArrayIn ([In, MarshalAs (UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)] object[] array);
}
[System.Runtime.InteropServices.GuidAttribute ("00000000-0000-0000-0000-000000000002")]
public virtual extern int Return22NoICall();
[MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern int IntOut();
+ [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+ public virtual extern void ArrayIn ([In, MarshalAs (UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)] object[] array);
}
[System.Runtime.InteropServices.GuidAttribute ("00000000-0000-0000-0000-000000000002")]
val = 33;
return 0;
}
+
+ public int ArrayIn(object[] array)
+ {
+ if (array.Length != 2)
+ return 40;
+ if (array.Rank != 1)
+ return 41;
+ if (array.GetLowerBound(0) != 0)
+ return 42;
+ if (array.GetUpperBound(0) != 1)
+ return 43;
+ if (array[0] is string)
+ {
+ if ((array[0] as string) != "Test")
+ return 44;
+ }
+ else
+ return 45;
+ if (array[1] is int)
+ {
+ if ((int)array[1] != 2345)
+ return 46;
+ }
+ else
+ return 47;
+
+ return 444;
+ }
}
public class ManagedTest : ITest
{
return 33;
}
+
+ public void ArrayIn(object[] array)
+ {
+ if (array.Length != 2)
+ status = 40;
+ else if (array.Rank != 1)
+ status = 41;
+ else if (array.GetLowerBound(0) != 0)
+ status = 42;
+ else if (array.GetUpperBound(0) != 1)
+ status = 43;
+ else if (array[0] is string)
+ {
+ if ((array[0] as string) != "Test")
+ status = 44;
+ }
+ else if (array[1] is int)
+ {
+ if ((int)array[1] != 2345)
+ status = 45;
+ }
+
+ status = 444;
+ }
}
[ComVisible (true)]
int (STDCALL *ITestOut)(MonoComObject* pUnk, MonoComObject* *ppUnk);
int (STDCALL *Return22NoICall)(MonoComObject* pUnk);
int (STDCALL *IntOut)(MonoComObject* pUnk, int *a);
+ int (STDCALL *ArrayIn)(MonoComObject* pUnk, void *array);
} MonoIUnknown;
struct MonoComObject
return S_OK;
}
+LIBTEST_API int STDCALL
+ArrayIn(MonoComObject* pUnk, void *array)
+{
+ return S_OK;
+}
+
static void create_com_object (MonoComObject** pOut);
LIBTEST_API int STDCALL
(*pOut)->vtbl->get_ITest = get_ITest;
(*pOut)->vtbl->Return22NoICall = Return22NoICall;
(*pOut)->vtbl->IntOut = IntOut;
+ (*pOut)->vtbl->ArrayIn = ArrayIn;
}
static MonoComObject* same_object = NULL;
return hr;
}
+LIBTEST_API int STDCALL
+mono_test_marshal_safearray_in_ccw(MonoComObject *pUnk)
+{
+ SAFEARRAY *array;
+ VARIANT var;
+ long index;
+ int ret;
+
+ array = SafeArrayCreateVector(VT_VARIANT, 0, 2);
+
+ var.vt = VT_BSTR;
+ var.bstrVal = marshal_bstr_alloc("Test");
+ index = 0;
+ SafeArrayPutElement(array, &index, &var);
+
+ var.vt = VT_I4;
+ var.intVal = 2345;
+ index = 1;
+ SafeArrayPutElement(array, &index, &var);
+
+ ret = pUnk->vtbl->ArrayIn (pUnk, (void *)array);
+
+ SafeArrayDestroy(array);
+
+ return ret;
+}
+
#endif
static int call_managed_res;