bool ILNativeArrayMarshaler::CanMarshalViaPinning()
{
- return IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags) && (NULL == OleVariant::GetMarshalerForVarType(m_pargs->na.m_vt, TRUE));
+ // We can't pin an array if we have a marshaler for the var type
+ // or if we can't get a method-table representing the array (how we determine the offset to pin).
+ return IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags) && (NULL != m_pargs->na.m_pArrayMT) && (NULL == OleVariant::GetMarshalerForVarType(m_pargs->na.m_vt, TRUE));
}
void ILNativeArrayMarshaler::EmitMarshalViaPinning(ILCodeStream* pslILEmit)
CONTRACTL
{
STANDARD_VM_CHECK;
- PRECONDITION(IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags));
+ PRECONDITION(CanMarshalViaPinning());
}
CONTRACTL_END;
pslILEmit->EmitCONV_I();
// Optimize marshalling by emitting the data ptr offset directly into the IL stream
// instead of doing an FCall to recalulate it each time when possible.
- pslILEmit->EmitLDC(ArrayBase::GetDataPtrOffset(m_pargs->m_pMarshalInfo->GetArrayElementTypeHandle().MakeSZArray().GetMethodTable()));
+ pslILEmit->EmitLDC(ArrayBase::GetDataPtrOffset(m_pargs->na.m_pArrayMT));
pslILEmit->EmitADD();
EmitStoreNativeValue(pslILEmit);
}
}
+ m_args.na.m_pArrayMT = arrayTypeHnd.GetMethodTable();
+
// Handle retrieving the information for the array type.
IfFailGoto(HandleArrayElemType(&ParamInfo, thElement, asArray->GetRank(), mtype == ELEMENT_TYPE_SZARRAY, isParam, pAssembly), lFail);
break;
[DllImport("MarshalArrayLPArrayNative")]
private static extern bool CStyle_Array_Bool_Out(
[Out] bool[] actual, int cActual);
+
+ [DllImport("MarshalArrayLPArrayNative")]
+ private static extern int Get_Multidimensional_Array_Sum(int[,] array, int rows, int columns);
#endregion
#region Marshal ByVal
private const int ARRAY_SIZE = 100;
+ private const int ROWS = 3;
+
+ private const int COLUMNS = 2;
+
private static T[] InitArray<T>(int size)
{
T[] array = new T[size];
return array;
}
+ private static int[,] InitMultidimensionalBlittableArray(int rows, int columns)
+ {
+ int[,] array = new int[rows, columns];
+
+ for (int i = 0; i < array.GetLength(0); i++)
+ {
+ for (int j = 0; j < array.GetLength(1); j++)
+ {
+ array[i, j] = i * j;
+ }
+ }
+ return array;
+ }
+
private static void TestMarshalByVal_NoAttributes()
{
Console.WriteLine("ByVal marshaling CLR array as c-style-array no attributes");
#endregion
+ private static void TestMultidimensional()
+ {
+ Console.WriteLine("================== [Get_Multidimensional_Array_Sum] ============");
+ int[,] array = InitMultidimensionalBlittableArray(ROWS, COLUMNS);
+ int sum = 0;
+ foreach (int item in array)
+ {
+ sum += item;
+ }
+
+ Assert.AreEqual(sum, Get_Multidimensional_Array_Sum(array, ROWS, COLUMNS));
+ }
+
public static int Main()
{
try
TestMarshalByVal_In();
TestMarshalInOut_ByVal();
TestMarshalOut_ByVal();
+ TestMultidimensional();
Console.WriteLine("\nTest PASS.");
return 100;