1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
6 using System.Runtime.InteropServices;
9 public class ArrayMarshal
11 public struct TestStruct
19 #region No attributes applied
21 [DllImport("MarshalArrayLPArrayNative")]
22 private static extern bool CStyle_Array_Int(int[] actual, int cActual);
24 [DllImport("MarshalArrayLPArrayNative")]
25 private static extern bool CStyle_Array_Uint(uint[] actual, int cActual);
27 [DllImport("MarshalArrayLPArrayNative")]
28 private static extern bool CStyle_Array_Short(short[] actual, int cActual);
30 [DllImport("MarshalArrayLPArrayNative")]
31 private static extern bool CStyle_Array_Word(ushort[] actual, int cActual);
33 [DllImport("MarshalArrayLPArrayNative")]
34 private static extern bool CStyle_Array_Long64(long[] actual, int cActual);
36 [DllImport("MarshalArrayLPArrayNative")]
37 private static extern bool CStyle_Array_ULong64(ulong[] actual, int cActual);
39 [DllImport("MarshalArrayLPArrayNative")]
40 private static extern bool CStyle_Array_Double(double[] actual, int cActual);
42 [DllImport("MarshalArrayLPArrayNative")]
43 private static extern bool CStyle_Array_Float(float[] actual, int cActual);
45 [DllImport("MarshalArrayLPArrayNative")]
46 private static extern bool CStyle_Array_Byte(byte[] actual, int cActual);
48 [DllImport("MarshalArrayLPArrayNative")]
49 private static extern bool CStyle_Array_Char(char[] actual, int cActual);
51 [DllImport("MarshalArrayLPArrayNative")]
52 private static extern bool CStyle_Array_LPCSTR(string[] actual, int cActual);
54 [DllImport("MarshalArrayLPArrayNative")]
55 private static extern bool CStyle_Array_LPSTR(string[] actual, int cActual);
57 [DllImport("MarshalArrayLPArrayNative")]
58 private static extern bool CStyle_Array_Struct(TestStruct[] actual, int cActual);
60 [DllImport("MarshalArrayLPArrayNative")]
61 private static extern bool CStyle_Array_Bool(bool[] actual, int cActual);
63 [DllImport("MarshalArrayLPArrayNative")]
64 private static extern bool CStyle_Array_Object(object[] actual, int cActual);
67 #region InAttribute attribute applied
69 [DllImport("MarshalArrayLPArrayNative", EntryPoint = "CStyle_Array_Int")]
70 private static extern bool CStyle_Array_Int_In([In]int[] actual, int cActual);
72 [DllImport("MarshalArrayLPArrayNative", EntryPoint = "CStyle_Array_Uint")]
73 private static extern bool CStyle_Array_Uint_In([In]uint[] actual, int cActual);
75 [DllImport("MarshalArrayLPArrayNative", EntryPoint = "CStyle_Array_Short")]
76 private static extern bool CStyle_Array_Short_In([In]short[] actual, int cActual);
78 [DllImport("MarshalArrayLPArrayNative", EntryPoint = "CStyle_Array_Word")]
79 private static extern bool CStyle_Array_Word_In([In]ushort[] actual, int cActual);
81 [DllImport("MarshalArrayLPArrayNative", EntryPoint = "CStyle_Array_Long64")]
82 private static extern bool CStyle_Array_Long64_In([In]long[] actual, int cActual);
84 [DllImport("MarshalArrayLPArrayNative", EntryPoint = "CStyle_Array_ULong64")]
85 private static extern bool CStyle_Array_ULong64_In([In]ulong[] actual, int cActual);
87 [DllImport("MarshalArrayLPArrayNative", EntryPoint = "CStyle_Array_Double")]
88 private static extern bool CStyle_Array_Double_In([In]double[] actual, int cActual);
90 [DllImport("MarshalArrayLPArrayNative", EntryPoint = "CStyle_Array_Float")]
91 private static extern bool CStyle_Array_Float_In([In]float[] actual, int cActual);
93 [DllImport("MarshalArrayLPArrayNative", EntryPoint = "CStyle_Array_Byte")]
94 private static extern bool CStyle_Array_Byte_In([In]byte[] actual, int cActual);
96 [DllImport("MarshalArrayLPArrayNative", EntryPoint = "CStyle_Array_Char")]
97 private static extern bool CStyle_Array_Char_In([In]char[] actual, int cActual);
99 [DllImport("MarshalArrayLPArrayNative", EntryPoint = "CStyle_Array_LPCSTR")]
100 private static extern bool CStyle_Array_LPCSTR_In([In]string[] actual, int cActual);
102 [DllImport("MarshalArrayLPArrayNative", EntryPoint = "CStyle_Array_LPSTR")]
103 private static extern bool CStyle_Array_LPSTR_In([In]string[] actual, int cActual);
105 [DllImport("MarshalArrayLPArrayNative", EntryPoint = "CStyle_Array_Struct")]
106 private static extern bool CStyle_Array_Struct_In([In]TestStruct[] actual, int cActual);
108 [DllImport("MarshalArrayLPArrayNative", EntryPoint = "CStyle_Array_Bool")]
109 private static extern bool CStyle_Array_Bool_In([In]bool[] actual, int cActual);
111 [DllImport("MarshalArrayLPArrayNative", EntryPoint = "CStyle_Array_Object")]
112 private static extern bool CStyle_Array_Object_In([In]object[] actual, int cActual);
115 #region InAttribute and OutAttribute attributes applied
117 [DllImport("MarshalArrayLPArrayNative")]
118 private static extern bool CStyle_Array_Int_InOut(
119 [In, Out] int[] actual, int cActual);
121 [DllImport("MarshalArrayLPArrayNative")]
122 private static extern bool CStyle_Array_Int_InOut_Null(
123 [In, Out] int[] actual);
125 [DllImport("MarshalArrayLPArrayNative")]
126 private static extern bool CStyle_Array_Int_InOut_ZeroLength(
127 [In, Out] int[] actual);
129 [DllImport("MarshalArrayLPArrayNative")]
130 private static extern bool CStyle_Array_Object_InOut(
131 [In, Out] object[] actual, int cActual);
133 [DllImport("MarshalArrayLPArrayNative")]
134 private static extern bool CStyle_Array_Uint_InOut(
135 [In, Out] uint[] actual, int cActual);
137 [DllImport("MarshalArrayLPArrayNative")]
138 private static extern bool CStyle_Array_Short_InOut(
139 [In, Out] short[] actual, int cActual);
141 [DllImport("MarshalArrayLPArrayNative")]
142 private static extern bool CStyle_Array_Word_InOut(
143 [In, Out] ushort[] actual, int cActual);
145 [DllImport("MarshalArrayLPArrayNative")]
146 private static extern bool CStyle_Array_Long64_InOut(
147 [In, Out] long[] actual, int cActual);
149 [DllImport("MarshalArrayLPArrayNative")]
150 private static extern bool CStyle_Array_ULong64_InOut(
151 [In, Out] ulong[] actual, int cActual);
153 [DllImport("MarshalArrayLPArrayNative")]
154 private static extern bool CStyle_Array_Double_InOut(
155 [In, Out] double[] actual, int cActual);
157 [DllImport("MarshalArrayLPArrayNative")]
158 private static extern bool CStyle_Array_Float_InOut(
159 [In, Out] float[] actual, int cActual);
161 [DllImport("MarshalArrayLPArrayNative")]
162 private static extern bool CStyle_Array_Byte_InOut(
163 [In, Out] byte[] actual, int cActual);
165 [DllImport("MarshalArrayLPArrayNative")]
166 private static extern bool CStyle_Array_Char_InOut(
167 [In, Out] char[] actual, int cActual);
169 [DllImport("MarshalArrayLPArrayNative")]
170 private static extern bool CStyle_Array_LPSTR_InOut(
171 [In, Out] string[] actual, int cActual);
173 [DllImport("MarshalArrayLPArrayNative")]
174 private static extern bool CStyle_Array_Struct_InOut(
175 [In, Out] TestStruct[] actual, int cActual);
177 [DllImport("MarshalArrayLPArrayNative")]
178 private static extern bool CStyle_Array_Bool_InOut(
179 [In, Out] bool[] actual, int cActual);
182 #region OutAttribute attributes applied
184 [DllImport("MarshalArrayLPArrayNative")]
185 private static extern bool CStyle_Array_Int_Out(
186 [Out] int[] actual, int cActual);
188 [DllImport("MarshalArrayLPArrayNative")]
189 private static extern bool CStyle_Array_Int_Out_Null(
192 [DllImport("MarshalArrayLPArrayNative")]
193 private static extern bool CStyle_Array_Int_Out_ZeroLength(
196 [DllImport("MarshalArrayLPArrayNative")]
197 private static extern bool CStyle_Array_Object_Out(
198 [Out] object[] actual, int cActual);
200 [DllImport("MarshalArrayLPArrayNative")]
201 private static extern bool CStyle_Array_Uint_Out(
202 [Out] uint[] actual, int cActual);
204 [DllImport("MarshalArrayLPArrayNative")]
205 private static extern bool CStyle_Array_Short_Out(
206 [Out] short[] actual, int cActual);
208 [DllImport("MarshalArrayLPArrayNative")]
209 private static extern bool CStyle_Array_Word_Out(
210 [Out] ushort[] actual, int cActual);
212 [DllImport("MarshalArrayLPArrayNative")]
213 private static extern bool CStyle_Array_Long64_Out(
214 [Out] long[] actual, int cActual);
216 [DllImport("MarshalArrayLPArrayNative")]
217 private static extern bool CStyle_Array_ULong64_Out(
218 [Out] ulong[] actual, int cActual);
220 [DllImport("MarshalArrayLPArrayNative")]
221 private static extern bool CStyle_Array_Double_Out(
222 [Out] double[] actual, int cActual);
224 [DllImport("MarshalArrayLPArrayNative")]
225 private static extern bool CStyle_Array_Float_Out(
226 [Out] float[] actual, int cActual);
228 [DllImport("MarshalArrayLPArrayNative")]
229 private static extern bool CStyle_Array_Byte_Out(
230 [Out] byte[] actual, int cActual);
232 [DllImport("MarshalArrayLPArrayNative")]
233 private static extern bool CStyle_Array_Char_Out(
234 [Out] char[] actual, int cActual);
236 [DllImport("MarshalArrayLPArrayNative")]
237 private static extern bool CStyle_Array_LPSTR_Out(
238 [Out] string[] actual, int cActual);
240 [DllImport("MarshalArrayLPArrayNative")]
241 private static extern bool CStyle_Array_Struct_Out(
242 [Out] TestStruct[] actual, int cActual);
244 [DllImport("MarshalArrayLPArrayNative")]
245 private static extern bool CStyle_Array_Bool_Out(
246 [Out] bool[] actual, int cActual);
249 #region Marshal ByVal
251 private const int ARRAY_SIZE = 100;
253 private static T[] InitArray<T>(int size)
255 T[] array = new T[size];
257 for (int i = 0; i < array.Length; ++i)
258 array[i] = (T)Convert.ChangeType(i, typeof(T));
263 private static bool[] InitBoolArray(int size)
265 bool[] array = new bool[size];
267 for (int i = 0; i < array.Length; ++i)
278 private static TestStruct[] InitStructArray(int size)
280 TestStruct[] array = new TestStruct[size];
282 for (int i = 0; i < array.Length; ++i)
287 array[i].str = i.ToString();
293 private static void TestMarshalByVal_NoAttributes()
295 Console.WriteLine("ByVal marshaling CLR array as c-style-array no attributes");
297 Assert.IsTrue(CStyle_Array_Int(InitArray<int>(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Int");
298 Assert.IsTrue(CStyle_Array_Uint(InitArray<uint>(ARRAY_SIZE), ARRAY_SIZE),"CStyle_Array_Uint") ;
299 Assert.IsTrue(CStyle_Array_Short(InitArray<short>(ARRAY_SIZE), ARRAY_SIZE),"CStyle_Array_Short");
300 Assert.IsTrue(CStyle_Array_Word(InitArray<ushort>(ARRAY_SIZE), ARRAY_SIZE),"CStyle_Array_Word");
301 Assert.IsTrue(CStyle_Array_Long64(InitArray<long>(ARRAY_SIZE), ARRAY_SIZE),"CStyle_Array_Long64");
302 Assert.IsTrue(CStyle_Array_ULong64(InitArray<ulong>(ARRAY_SIZE), ARRAY_SIZE),"CStyle_Array_ULong64");
303 Assert.IsTrue(CStyle_Array_Double(InitArray<double>(ARRAY_SIZE), ARRAY_SIZE),"CStyle_Array_Double");
304 Assert.IsTrue(CStyle_Array_Float(InitArray<float>(ARRAY_SIZE), ARRAY_SIZE),"CStyle_Array_Float");
305 Assert.IsTrue(CStyle_Array_Byte(InitArray<byte>(ARRAY_SIZE), ARRAY_SIZE),"CStyle_Array_Byte");
306 Assert.IsTrue(CStyle_Array_Char(InitArray<char>(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Char");
308 string[] strArr = InitArray<string>(ARRAY_SIZE);
309 // Test nesting null value scenario
310 strArr[strArr.Length / 2] = null;
311 Assert.IsTrue(CStyle_Array_LPCSTR(strArr, ARRAY_SIZE), "CStyle_Array_LPCSTR");
312 Assert.IsTrue(CStyle_Array_LPSTR(strArr, ARRAY_SIZE), "CStyle_Array_LPSTR");
313 Assert.IsTrue(CStyle_Array_Struct(InitStructArray(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Struct");
315 Assert.IsTrue(CStyle_Array_Bool(InitBoolArray(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Bool");
317 if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
319 object[] oArr = InitArray<object>(ARRAY_SIZE);
320 // Test nesting null value scenario
321 oArr[oArr.Length / 2] = null;
322 Assert.IsTrue(CStyle_Array_Object(oArr, ARRAY_SIZE), "CStyle_Array_Object");
326 private static void TestMarshalByVal_In()
328 Console.WriteLine("ByVal marshaling CLR array as c-style-array with InAttribute applied");
330 Assert.IsTrue(CStyle_Array_Int_In(InitArray<int>(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Int_In");
331 Assert.IsTrue(CStyle_Array_Uint_In(InitArray<uint>(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Uint_In");
332 Assert.IsTrue(CStyle_Array_Short_In(InitArray<short>(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Short_In");
333 Assert.IsTrue(CStyle_Array_Word_In(InitArray<ushort>(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Word_In");
334 Assert.IsTrue(CStyle_Array_Long64_In(InitArray<long>(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Long64_In");
335 Assert.IsTrue(CStyle_Array_ULong64_In(InitArray<ulong>(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_ULong64_In");
336 Assert.IsTrue(CStyle_Array_Double_In(InitArray<double>(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Double_In");
337 Assert.IsTrue(CStyle_Array_Float_In(InitArray<float>(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Float_In");
338 Assert.IsTrue(CStyle_Array_Byte_In(InitArray<byte>(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Byte_In");
339 Assert.IsTrue(CStyle_Array_Char_In(InitArray<char>(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Char_In");
341 string[] strArr = InitArray<string>(ARRAY_SIZE);
342 // Test nesting null value scenario
343 strArr[strArr.Length / 2] = null;
345 Assert.IsTrue(CStyle_Array_LPCSTR_In(strArr, ARRAY_SIZE), "CStyle_Array_LPCSTR_In");
346 Assert.IsTrue(CStyle_Array_LPSTR_In(strArr, ARRAY_SIZE), "CStyle_Array_LPSTR_In");
347 Assert.IsTrue(CStyle_Array_Struct_In(InitStructArray(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Struct_In");
348 Assert.IsTrue(CStyle_Array_Bool_In(InitBoolArray(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Bool_In");
349 if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
351 object[] oArr = InitArray<object>(ARRAY_SIZE);
352 // Test nesting null value scenario
353 oArr[oArr.Length / 2] = null;
354 Assert.IsTrue(CStyle_Array_Object_In(oArr, ARRAY_SIZE), "CStyle_Array_Object_In");
360 #region Marshal InOut ByVal
362 private static void TestMarshalInOut_ByVal()
364 Console.WriteLine("By value marshaling CLR array as c-style-array with InAttribute and OutAttribute applied");
365 Console.WriteLine("CStyle_Array_Int_InOut");
366 int[] iArr = InitArray<int>(ARRAY_SIZE);
367 Assert.IsTrue(CStyle_Array_Int_InOut(iArr, ARRAY_SIZE), "CStyle_Array_Int_InOut");
368 Assert.IsTrue(Equals<int>(iArr, GetExpectedOutArray<int>(ARRAY_SIZE)), "CStyle_Array_Int_InOut:Equals<int>");
370 Console.WriteLine("CStyle_Array_Int_InOut_Null");
371 int[] iArrNull = null;
372 Assert.IsTrue(CStyle_Array_Int_InOut_Null(iArrNull), "CStyle_Array_Int_InOut_Null");
373 Assert.IsNull(iArrNull, "CStyle_Array_Int_InOut_Null:Equals<null>");
375 Console.WriteLine("CStyle_Array_Int_InOut_ZeroLength");
376 int[] iArrLength0 = InitArray<int>(0);
377 Assert.IsTrue(CStyle_Array_Int_InOut_ZeroLength(iArrLength0), "CStyle_Array_Int_InOut_ZeroLength");
378 Assert.AreEqual(0, iArrLength0.Length, "CStyle_Array_Int_InOut_ZeroLength:Length<!0>");
380 Console.WriteLine("CStyle_Array_Uint_InOut");
381 uint[] uiArr = InitArray<uint>(ARRAY_SIZE);
382 Assert.IsTrue(CStyle_Array_Uint_InOut(uiArr, ARRAY_SIZE), "CStyle_Array_Uint_InOut");
383 Assert.IsTrue(Equals<uint>(uiArr, GetExpectedOutArray<uint>(ARRAY_SIZE)), "CStyle_Array_Uint_InOut:Equals<uint>");
385 Console.WriteLine("CStyle_Array_Short_InOut");
386 short[] sArr = InitArray<short>(ARRAY_SIZE);
387 Assert.IsTrue(CStyle_Array_Short_InOut(sArr, ARRAY_SIZE), "CStyle_Array_Short_InOut");
388 Assert.IsTrue(Equals<short>(sArr, GetExpectedOutArray<short>(ARRAY_SIZE)), "CStyle_Array_Short_InOut:Equals<short>");
390 Console.WriteLine("CStyle_Array_Word_InOut");
391 ushort[] usArr = InitArray<ushort>(ARRAY_SIZE);
392 Assert.IsTrue(CStyle_Array_Word_InOut(usArr, ARRAY_SIZE), "CStyle_Array_Word_InOut");
393 Assert.IsTrue(Equals<ushort>(usArr, GetExpectedOutArray<ushort>(ARRAY_SIZE)), "CStyle_Array_Word_InOut:Equals<ushort>");
395 Console.WriteLine("CStyle_Array_Long64_InOut");
396 long[] lArr = InitArray<long>(ARRAY_SIZE);
397 Assert.IsTrue(CStyle_Array_Long64_InOut(lArr, ARRAY_SIZE), "CStyle_Array_Long64_InOut");
398 Assert.IsTrue(Equals<long>(lArr, GetExpectedOutArray<long>(ARRAY_SIZE)), "CStyle_Array_Long64_InOut:Equals<long>");
400 Console.WriteLine("CStyle_Array_ULong64_InOut");
401 ulong[] ulArr = InitArray<ulong>(ARRAY_SIZE);
402 Assert.IsTrue(CStyle_Array_ULong64_InOut(ulArr, ARRAY_SIZE), "CStyle_Array_ULong64_InOut");
403 Assert.IsTrue(Equals<ulong>(ulArr, GetExpectedOutArray<ulong>(ARRAY_SIZE)), "CStyle_Array_ULong64_InOut:Equals<ulong>");
405 Console.WriteLine("CStyle_Array_Double_InOut");
406 double[] dArr = InitArray<double>(ARRAY_SIZE);
407 Assert.IsTrue(CStyle_Array_Double_InOut(dArr, ARRAY_SIZE), "CStyle_Array_Double_InOut");
408 Assert.IsTrue(Equals<double>(dArr, GetExpectedOutArray<double>(ARRAY_SIZE)), "CStyle_Array_Double_InOut:Equals<double>");
410 Console.WriteLine("CStyle_Array_Float_InOut");
411 float[] fArr = InitArray<float>(ARRAY_SIZE);
412 Assert.IsTrue(CStyle_Array_Float_InOut(fArr, ARRAY_SIZE), "CStyle_Array_Float_InOut");
413 Assert.IsTrue(Equals<float>(fArr, GetExpectedOutArray<float>(ARRAY_SIZE)), "CStyle_Array_Float_InOut:Equals<float>");
415 Console.WriteLine("CStyle_Array_Byte_InOut");
416 byte[] bArr = InitArray<byte>(ARRAY_SIZE);
417 Assert.IsTrue(CStyle_Array_Byte_InOut(bArr, ARRAY_SIZE), "CStyle_Array_Byte_InOut");
418 Assert.IsTrue(Equals<byte>(bArr, GetExpectedOutArray<byte>(ARRAY_SIZE)), "CStyle_Array_Byte_InOut:Equals<byte>");
420 Console.WriteLine("CStyle_Array_Char_InOut");
421 char[] cArr = InitArray<char>(ARRAY_SIZE);
422 Assert.IsTrue(CStyle_Array_Char_InOut(cArr, ARRAY_SIZE), "CStyle_Array_Char_InOut");
423 Assert.IsTrue(Equals<char>(cArr, GetExpectedOutArray<char>(ARRAY_SIZE)), "CStyle_Array_Char_InOut:Equals<char>");
425 Console.WriteLine("CStyle_Array_LPSTR_InOut");
426 string[] strArr = InitArray<string>(ARRAY_SIZE);
427 strArr[strArr.Length / 2] = null;
428 Assert.IsTrue(CStyle_Array_LPSTR_InOut(strArr, ARRAY_SIZE), "CStyle_Array_LPSTR_InOut");
429 string[] expectedArr = GetExpectedOutArray<string>(ARRAY_SIZE);
430 // Test nesting null value scenario
431 expectedArr[expectedArr.Length / 2 - 1] = null;
432 Assert.IsTrue(Equals<string>(strArr, expectedArr), "CStyle_Array_LPSTR_InOut:Equals<string>");
434 Console.WriteLine("CStyle_Array_Struct_InOut");
435 TestStruct[] tsArr = InitStructArray(ARRAY_SIZE);
436 Assert.IsTrue(CStyle_Array_Struct_InOut(tsArr, ARRAY_SIZE), "CStyle_Array_Struct_InOut");
437 Assert.IsTrue(Equals<TestStruct>(tsArr, GetExpectedOutStructArray(ARRAY_SIZE)), "CStyle_Array_Struct_InOut:Equals<TestStruct>");
439 Console.WriteLine("CStyle_Array_Bool_InOut");
440 bool[] boolArr = InitBoolArray(ARRAY_SIZE);
441 Assert.IsTrue(CStyle_Array_Bool_InOut(boolArr, ARRAY_SIZE), "CStyle_Array_Bool_InOut");
442 Assert.IsTrue(Equals<bool>(boolArr, GetExpectedOutBoolArray(ARRAY_SIZE)), "CStyle_Array_Bool_InOut:Equals<bool>");
444 if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
446 Console.WriteLine("CStyle_Array_Object_InOut");
447 object[] oArr = InitArray<object>(ARRAY_SIZE);
448 oArr[oArr.Length / 2] = null;
449 Assert.IsTrue(CStyle_Array_Object_InOut(oArr, ARRAY_SIZE), "CStyle_Array_Object_InOut");
451 object[] expectedOArr = GetExpectedOutArray<object>(ARRAY_SIZE);
452 // Test nesting null value scenario
453 expectedOArr[expectedOArr.Length / 2 - 1] = null;
454 Assert.IsTrue(Equals<object>(oArr, expectedOArr), "CStyle_Array_Object_InOut:Equals<object>");
458 private static bool Equals<T>(T[] arr1, T[] arr2)
460 if (arr1 == null && arr2 == null)
462 else if (arr1 == null && arr2 != null)
464 else if (arr1 != null && arr2 == null)
466 else if (arr1.Length != arr2.Length)
469 for (int i = 0; i < arr2.Length; ++i)
471 if (!Object.Equals(arr1[i], arr2[i]))
473 Console.WriteLine("Array marshaling error: Index: {0} : Actual:{1}, Expected:{2},", i, arr1[i], arr2[i]);
481 private static T[] GetExpectedOutArray<T>(int size)
483 T[] array = new T[size];
485 for (int i = array.Length - 1; i >= 0; --i)
486 array[i] = (T)Convert.ChangeType(array.Length - 1 - i, typeof(T));
491 private static bool[] GetExpectedOutBoolArray(int size)
493 bool[] array = new bool[size];
495 for (int i = 0; i < array.Length; ++i)
506 private static TestStruct[] GetExpectedOutStructArray(int size)
508 TestStruct[] array = new TestStruct[size];
510 for (int i = array.Length - 1; i >= 0; --i)
512 int v = array.Length - 1 - i;
516 array[i].str = v.ToString();
524 #region Marshal Out ByVal
526 private static void TestMarshalOut_ByVal()
528 Console.WriteLine("By value marshaling CLR array as c-style-array with OutAttribute applied");
530 Console.WriteLine("CStyle_Array_Int_Out");
531 int[] iArr = new int[ARRAY_SIZE];
532 Assert.IsTrue(CStyle_Array_Int_Out(iArr, ARRAY_SIZE), "CStyle_Array_Int_Out");
533 Assert.IsTrue(Equals<int>(iArr, GetExpectedOutArray<int>(ARRAY_SIZE)), "CStyle_Array_Int_Out:Equals<int>");
535 Console.WriteLine("CStyle_Array_Int_Out_Null");
536 int[] iArrNull = null;
537 Assert.IsTrue(CStyle_Array_Int_Out_Null(iArrNull), "CStyle_Array_Int_Out_Null");
538 Assert.IsNull(iArrNull, "CStyle_Array_Int_Out_Null:Equals<null>");
540 Console.WriteLine("CStyle_Array_Int_Out_ZeroLength");
541 int[] iArrLength0 = new int[0];
542 Assert.IsTrue(CStyle_Array_Int_Out_ZeroLength(iArrLength0), "CStyle_Array_Int_Out_ZeroLength");
543 Assert.AreEqual(0, iArrLength0.Length, "CStyle_Array_Int_Out_ZeroLength:Length<!0>");
545 Console.WriteLine("CStyle_Array_Uint_Out");
546 uint[] uiArr = new uint[ARRAY_SIZE];
547 Assert.IsTrue(CStyle_Array_Uint_Out(uiArr, ARRAY_SIZE), "CStyle_Array_Uint_Out");
548 Assert.IsTrue(Equals<uint>(uiArr, GetExpectedOutArray<uint>(ARRAY_SIZE)), "CStyle_Array_Uint_Out:Equals<uint>");
550 Console.WriteLine("CStyle_Array_Short_Out");
551 short[] sArr = new short[ARRAY_SIZE];
552 Assert.IsTrue(CStyle_Array_Short_Out(sArr, ARRAY_SIZE), "CStyle_Array_Short_Out");
553 Assert.IsTrue(Equals<short>(sArr, GetExpectedOutArray<short>(ARRAY_SIZE)), "CStyle_Array_Short_Out:Equals<short>");
555 Console.WriteLine("CStyle_Array_Word_Out");
556 ushort[] usArr = new ushort[ARRAY_SIZE];
557 Assert.IsTrue(CStyle_Array_Word_Out(usArr, ARRAY_SIZE), "CStyle_Array_Word_Out");
558 Assert.IsTrue(Equals<ushort>(usArr, GetExpectedOutArray<ushort>(ARRAY_SIZE)), "CStyle_Array_Word_Out:Equals<ushort>");
560 Console.WriteLine("CStyle_Array_Long64_Out");
561 long[] lArr = new long[ARRAY_SIZE];
562 Assert.IsTrue(CStyle_Array_Long64_Out(lArr, ARRAY_SIZE), "CStyle_Array_Long64_Out");
563 Assert.IsTrue(Equals<long>(lArr, GetExpectedOutArray<long>(ARRAY_SIZE)), "CStyle_Array_Long64_Out:Equals<long>");
565 Console.WriteLine("CStyle_Array_ULong64_Out");
566 ulong[] ulArr = new ulong[ARRAY_SIZE];
567 Assert.IsTrue(CStyle_Array_ULong64_Out(ulArr, ARRAY_SIZE), "CStyle_Array_ULong64_Out");
568 Assert.IsTrue(Equals<ulong>(ulArr, GetExpectedOutArray<ulong>(ARRAY_SIZE)), "CStyle_Array_ULong64_Out:Equals<ulong>");
570 Console.WriteLine("CStyle_Array_Double_Out");
571 double[] dArr = new double[ARRAY_SIZE];
572 Assert.IsTrue(CStyle_Array_Double_Out(dArr, ARRAY_SIZE), "CStyle_Array_Double_Out");
573 Assert.IsTrue(Equals<double>(dArr, GetExpectedOutArray<double>(ARRAY_SIZE)), "CStyle_Array_Double_Out:Equals<double>");
575 Console.WriteLine("CStyle_Array_Float_Out");
576 float[] fArr = new float[ARRAY_SIZE];
577 Assert.IsTrue(CStyle_Array_Float_Out(fArr, ARRAY_SIZE), "CStyle_Array_Float_Out");
578 Assert.IsTrue(Equals<float>(fArr, GetExpectedOutArray<float>(ARRAY_SIZE)), "CStyle_Array_Float_Out:Equals<float>");
580 Console.WriteLine("CStyle_Array_Byte_Out");
581 byte[] bArr = new byte[ARRAY_SIZE];
582 Assert.IsTrue(CStyle_Array_Byte_Out(bArr, ARRAY_SIZE), "CStyle_Array_Byte_Out");
583 Assert.IsTrue(Equals<byte>(bArr, GetExpectedOutArray<byte>(ARRAY_SIZE)), "CStyle_Array_Byte_Out:Equals<byte>");
585 Console.WriteLine("CStyle_Array_Char_Out");
586 char[] cArr = new char[ARRAY_SIZE];
587 Assert.IsTrue(CStyle_Array_Char_Out(cArr, ARRAY_SIZE), "CStyle_Array_Char_Out");
588 Assert.IsTrue(Equals<char>(cArr, GetExpectedOutArray<char>(ARRAY_SIZE)), "CStyle_Array_Char_Out:Equals<char>");
590 Console.WriteLine("CStyle_Array_LPSTR_Out");
591 string[] strArr = new string[ARRAY_SIZE];
592 Assert.IsTrue(CStyle_Array_LPSTR_Out(strArr, ARRAY_SIZE), "CStyle_Array_LPSTR_Out");
593 string[] expectedArr = GetExpectedOutArray<string>(ARRAY_SIZE);
594 // Test nesting null value scenario
595 expectedArr[expectedArr.Length / 2 - 1] = null;
596 Assert.IsTrue(Equals<string>(strArr, expectedArr), "CStyle_Array_LPSTR_Out:Equals<string>");
597 Console.WriteLine("CStyle_Array_Struct_Out");
598 TestStruct[] tsArr = new TestStruct[ARRAY_SIZE];
599 Assert.IsTrue(CStyle_Array_Struct_Out(tsArr, ARRAY_SIZE), "CStyle_Array_Struct_Out");
600 Assert.IsTrue(Equals<TestStruct>(tsArr, GetExpectedOutStructArray(ARRAY_SIZE)), "Equals<TestStruct>");
602 Console.WriteLine("CStyle_Array_Bool_Out");
603 bool[] boolArr = new bool[ARRAY_SIZE];
604 Assert.IsTrue(CStyle_Array_Bool_Out(boolArr, ARRAY_SIZE), "CStyle_Array_Bool_Out");
605 Assert.IsTrue(Equals<bool>(boolArr, GetExpectedOutBoolArray(ARRAY_SIZE)), "CStyle_Array_Bool_Out:Equals<bool>");
607 if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
609 Console.WriteLine("CStyle_Array_Object_Out");
610 object[] oArr = new object[ARRAY_SIZE];
611 Assert.IsTrue(CStyle_Array_Object_Out(oArr, ARRAY_SIZE), "CStyle_Array_Object_Out");
613 object[] expectedOArr = GetExpectedOutArray<object>(ARRAY_SIZE);
614 // Test nesting null value scenario
615 expectedOArr[expectedOArr.Length / 2 - 1] = null;
616 Assert.IsTrue(Equals<object>(oArr, expectedOArr), "CStyle_Array_Object_Out:Equals<object>");
622 public static int Main()
626 TestMarshalByVal_NoAttributes();
627 TestMarshalByVal_In();
628 TestMarshalInOut_ByVal();
629 TestMarshalOut_ByVal();
631 Console.WriteLine("\nTest PASS.");
636 Console.WriteLine($"\nTEST FAIL: {e.Message}");