From f5a23fe0e3120e449ddce4b9c025305a786a2481 Mon Sep 17 00:00:00 2001 From: Zeng Jiang Date: Fri, 16 Nov 2018 05:32:25 +0800 Subject: [PATCH] Add PInvoke/Array tests (#19266) * Add PInvoke/Array tests * Fix compile warnings * Get tests passing on Windows again. * Change error_t type to work xplat. * Change error_t in types.h as well * Clean up build slightly. * PR feedback and native test code refactoring. * Clean up header. * Add a xplat implementation of _itoa_s for our tests. * CHAR -> char * Make calling convention cdecl to avoid stdcall mangling. * Make return test native code cdecl as well (missed it before). * Fix bug in platformdefines _itoa_s * Return early in TP_itoX_s when num == 0 --- tests/src/Common/Platform/platformdefines.cpp | 45 +- tests/src/Common/Platform/platformdefines.h | 4 +- tests/src/Interop/CMakeLists.txt | 2 + tests/src/Interop/PInvoke/Array/MarshalArray.h | 329 ++++++ .../AsByValArray/AsByValArrayTest.cs | 1142 ++++++++++++++++++++ .../AsByValArray/AsByValArrayTest.csproj | 34 + .../AsByValArray/FldDef_DefaultArray.cs | 189 ++++ .../MarshalArrayAsField/AsLPArray/AsLPArrayTest.cs | 445 ++++++++ .../AsLPArray/AsLPArrayTest.csproj | 34 + .../AsLPArray/FldDef_LPArray.cs | 483 +++++++++ .../LPArrayNative/CMakeLists.txt | 15 + .../LPArrayNative/MarshalArrayByValArrayNative.cpp | 575 ++++++++++ .../MarshalArrayAsParam/AsDefault/AsDefaultTest.cs | 640 +++++++++++ .../AsDefault/AsDefaultTest.csproj | 34 + .../MarshalArrayAsParam/AsLPArray/AsLPArrayTest.cs | 650 +++++++++++ .../AsLPArray/AsLPArrayTest.csproj | 34 + .../LPArrayNative/CMakeLists.txt | 15 + .../LPArrayNative/MarshalArrayLPArrayNative.cpp | 1107 +++++++++++++++++++ tests/src/Interop/common/types.h | 2 +- 19 files changed, 5776 insertions(+), 3 deletions(-) create mode 100644 tests/src/Interop/PInvoke/Array/MarshalArray.h create mode 100644 tests/src/Interop/PInvoke/Array/MarshalArrayAsField/AsByValArray/AsByValArrayTest.cs create mode 100644 tests/src/Interop/PInvoke/Array/MarshalArrayAsField/AsByValArray/AsByValArrayTest.csproj create mode 100644 tests/src/Interop/PInvoke/Array/MarshalArrayAsField/AsByValArray/FldDef_DefaultArray.cs create mode 100644 tests/src/Interop/PInvoke/Array/MarshalArrayAsField/AsLPArray/AsLPArrayTest.cs create mode 100644 tests/src/Interop/PInvoke/Array/MarshalArrayAsField/AsLPArray/AsLPArrayTest.csproj create mode 100644 tests/src/Interop/PInvoke/Array/MarshalArrayAsField/AsLPArray/FldDef_LPArray.cs create mode 100644 tests/src/Interop/PInvoke/Array/MarshalArrayAsField/LPArrayNative/CMakeLists.txt create mode 100644 tests/src/Interop/PInvoke/Array/MarshalArrayAsField/LPArrayNative/MarshalArrayByValArrayNative.cpp create mode 100644 tests/src/Interop/PInvoke/Array/MarshalArrayAsParam/AsDefault/AsDefaultTest.cs create mode 100644 tests/src/Interop/PInvoke/Array/MarshalArrayAsParam/AsDefault/AsDefaultTest.csproj create mode 100644 tests/src/Interop/PInvoke/Array/MarshalArrayAsParam/AsLPArray/AsLPArrayTest.cs create mode 100644 tests/src/Interop/PInvoke/Array/MarshalArrayAsParam/AsLPArray/AsLPArrayTest.csproj create mode 100644 tests/src/Interop/PInvoke/Array/MarshalArrayAsParam/LPArrayNative/CMakeLists.txt create mode 100644 tests/src/Interop/PInvoke/Array/MarshalArrayAsParam/LPArrayNative/MarshalArrayLPArrayNative.cpp diff --git a/tests/src/Common/Platform/platformdefines.cpp b/tests/src/Common/Platform/platformdefines.cpp index 34cd360..61b91b3 100644 --- a/tests/src/Common/Platform/platformdefines.cpp +++ b/tests/src/Common/Platform/platformdefines.cpp @@ -208,8 +208,9 @@ error_t TP_itow_s(int num, LPWSTR buffer, size_t sizeInCharacters, int radix) // take care of the trivial case if (0 == num) { - buffer[0] = '\0'; + buffer[0] = '0'; buffer[1] = '\0'; + return 0; } // get length of final string (dumb implementation) @@ -235,6 +236,48 @@ error_t TP_itow_s(int num, LPWSTR buffer, size_t sizeInCharacters, int radix) return 0; } +error_t TP_itoa_s(int num, LPSTR buffer, size_t sizeInCharacters, int radix) +{ + size_t len; + int tmpNum; + + // only support radix == 10 and only positive numbers + if (10 != radix) return 1; + if (0 > num) return 2; + if (NULL == buffer) return 3; + if (2 > sizeInCharacters) return 4; + + // take care of the trivial case + if (0 == num) + { + buffer[0] = '0'; + buffer[1] = '\0'; + return 0; + } + + // get length of final string (dumb implementation) + len = 0; + tmpNum = num; + while (0 < tmpNum) + { + tmpNum /= 10; + len++; + } + + if (len >= sizeInCharacters) return 5; + + // convert num into a string (backwards) + buffer[len] = '\0'; + while(0 < num && 0 < len) + { + len--; + buffer[len] = (char)((num % 10) + '0'); + num /= 10; + } + + return 0; +} + LPWSTR TP_sstr(LPWSTR str, LPWSTR searchStr) { LPWSTR start; diff --git a/tests/src/Common/Platform/platformdefines.h b/tests/src/Common/Platform/platformdefines.h index 64b9c80..498c438 100644 --- a/tests/src/Common/Platform/platformdefines.h +++ b/tests/src/Common/Platform/platformdefines.h @@ -112,7 +112,7 @@ typedef const TCHAR* LPCTSTR; typedef void* FARPROC; typedef void* HMODULE; typedef void* ULONG_PTR; -typedef unsigned error_t; +typedef int error_t; typedef void* LPVOID; typedef unsigned char BYTE; typedef WCHAR OLECHAR; @@ -132,6 +132,7 @@ error_t TP_getenv_s(size_t* pReturnValue, LPWSTR buffer, size_t sizeInWords, LPC error_t TP_putenv_s(LPTSTR name, LPTSTR value); void TP_ZeroMemory(LPVOID buffer, size_t sizeInBytes); error_t TP_itow_s(int num, LPWSTR buffer, size_t sizeInCharacters, int radix); +error_t TP_itoa_s(int num, LPSTR buffer, size_t sizeInCharacters, int radix); LPWSTR TP_sstr(LPWSTR str, LPWSTR searchStr); LPSTR HackyConvertToSTR(LPWSTR pwszInput); DWORD TP_CreateThread(THREAD_ID* tThread, LPTHREAD_START_ROUTINE worker, LPVOID lpParameter); @@ -184,6 +185,7 @@ BSTR TP_SysAllocString(LPWSTR psz); #define _putenv_s TP_putenv_s #define ZeroMemory TP_ZeroMemory #define _itow_s TP_itow_s +#define _itoa_s TP_itoa_s #define wcsstr TP_sstr #define strcmp TP_scmp_s #define wcscmp TP_wcmp_s diff --git a/tests/src/Interop/CMakeLists.txt b/tests/src/Interop/CMakeLists.txt index de43fca..c509665 100644 --- a/tests/src/Interop/CMakeLists.txt +++ b/tests/src/Interop/CMakeLists.txt @@ -17,6 +17,8 @@ add_subdirectory(PInvoke/BestFitMapping/LPStr) add_subdirectory(PInvoke/Delegate/MarshalDelegateAsField) add_subdirectory(PInvoke/Delegate/MarshalDelegateAsParam) add_subdirectory(PInvoke/Primitives/Int) +add_subdirectory(PInvoke/Array/MarshalArrayAsField/LPArrayNative) +add_subdirectory(PInvoke/Array/MarshalArrayAsParam/LPArrayNative) add_subdirectory(PInvoke/Miscellaneous/HandleRef) add_subdirectory(PInvoke/Miscellaneous/MultipleAssembliesWithSamePInvoke) add_subdirectory(PInvoke/ExactSpelling) diff --git a/tests/src/Interop/PInvoke/Array/MarshalArray.h b/tests/src/Interop/PInvoke/Array/MarshalArray.h new file mode 100644 index 0000000..c3d027e --- /dev/null +++ b/tests/src/Interop/PInvoke/Array/MarshalArray.h @@ -0,0 +1,329 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#pragma once +#include +#include // required by itoa +#include +#include "platformdefines.h" + +////////////////////////////////////////////////////////////////////////////// +// Macro definitions +////////////////////////////////////////////////////////////////////////////// +#define ARRAY_SIZE 100 +#define ROWS 2 +#define COLUMNS 3 + +#define COUNTOF(__arr) sizeof(__arr) / sizeof(__arr[0]) +#define ELEM_PER_ROW_2D(__arr) (&(__arr[1][0]) - &(__arr[0][0])) +#define ROWS_2D(__arr) sizeof(__arr) / (ELEM_PER_ROW_2D(__arr) * sizeof(__arr[0][0])) + +#define ENTERFUNC() printf("============ [%s]\t ============\n", __FUNCTION__) + +#define CHECK_PARAM_NOT_EMPTY(__p) \ + ENTERFUNC(); \ + if ( (__p) == NULL ) \ + { \ + printf("[%s] Error: parameter actual is NULL\n", __FUNCTION__); \ + return false; \ + } + +#define CHECK_PARAM_EMPTY(__p) \ + ENTERFUNC(); \ + if ( __p != NULL ) \ + { \ + printf("[%s] Error: parameter ppActual is not NULL\n", __FUNCTION__); \ + return false; \ + } + +#define VERIFY_ERROR(__expect, __actual) \ + std::cout << '[' << __FUNCSIG__ << "] EXPECT: " << (__expect) << ", ACTUAL: " << (__actual) << std::endl + +#define TRACE(__msg) \ + std::cout << __msg << std::endl + +#define VERIFY_ERROR_MSG(__msg, __expect, __actual) \ + printf("["##__FUNCSIG__##"] "##__msg, (__expect), (__actual)) + +////////////////////////////////////////////////////////////////////////////// +// Verify helper methods +////////////////////////////////////////////////////////////////////////////// + +template +bool IsObjectEquals(const T& o1, const T& o2) +{ + return o1 == o2; +} + +template<> +bool IsObjectEquals(const LPSTR& o1, const LPSTR& o2) +{ + if (o1 == NULL) + { + return (o2 == NULL); + } + else if (o2 == NULL) + { + return false; + } + + size_t cLen1 = strlen(o1); + size_t cLen2 = strlen(o2); + + if (cLen1 != cLen2 ) + { + printf("Not equals in %s\n",__FUNCTION__); + return false; + } + + return strncmp(o1, o2, cLen1) == 0; +} + +template<> +bool IsObjectEquals(const LPCSTR& o1, const LPCSTR& o2) +{ + if (o1 == NULL) + { + return (o2 == NULL); + } + else if (o2 == NULL) + { + return false; + } + + size_t cLen1 = strlen(o1); + size_t cLen2 = strlen(o2); + + if (cLen1 != cLen2 ) + { + printf("Not equals in %s\n",__FUNCTION__); + return false; + } + + return strncmp(o1, o2, cLen1) == 0; +} + +#ifdef _WIN32 +template<> +bool IsObjectEquals(const BSTR& o1, const BSTR& o2) +{ + if (o1 == NULL) + { + return (o2 == NULL); + } + else if (o2 == NULL) + { + return false; + } + + UINT uLen1 = SysStringLen(o1); + UINT uLen2 = SysStringLen(o2); + + if (uLen1 != uLen2 ) + { + printf("Not equals in %s\n",__FUNCTION__); + return false; + } + + return memcmp(o1, o2, uLen1 * sizeof(*o1)) == 0; +} +#endif + +////////////////////////////////////////////////////////////////////////////// +// Test Data Structure +////////////////////////////////////////////////////////////////////////////// + +LPSTR ToString(int i) +{ + CHAR *pBuffer = (CHAR *)CoreClrAlloc(10 * sizeof(CHAR)); // 10 is enough for our case + _itoa_s(i, pBuffer, 10, 10); + + return pBuffer; +} + +#ifdef _WIN32 +BSTR ToBSTR(int i) +{ + BSTR bstrRet = NULL; + VarBstrFromI4(i, 0, 0, &bstrRet); + + return bstrRet; +} +#endif + +struct TestStruct +{ + inline TestStruct() + : x(0) + , d(0) + , l(0) + , str(NULL) + { + } + + inline TestStruct(int v) + : x(v) + , d(v) + , l(v) + { + str = ToString(v); + } + + int x; + double d; + LONG64 l; + LPSTR str; + + inline bool operator==(const TestStruct &other) const + { + return IsObjectEquals(x, other.x) && + IsObjectEquals(d, other.d) && + IsObjectEquals(l, other.l) && + IsObjectEquals(str, other.str); + } +}; + +typedef struct S2 +{ + INT i32; + UINT ui32; + SHORT s1; + WORD us1; + BYTE b; + CHAR sb; + SHORT i16; + WORD ui16; + LONG64 i64; + ULONG64 ui64; + FLOAT sgl; + DOUBLE d; +}S2; + +////////////////////////////////////////////////////////////////////////////// +// Other methods +////////////////////////////////////////////////////////////////////////////// + +#ifdef _WIN32 +// Do not output variants, and suppress the boring template compile warning +std::ostream &operator<<(std::ostream &ostr, VARIANT &v) +{ + return ostr; +} + +std::ostream &operator<<(std::ostream &ostr, BSTR &b) +{ + std::wcout << b; + return ostr; +} +#endif + +//////////////////////////////////method for struct S2//////////////////////////////////////////////// +void InstanceS2(S2 * pREC, int i32,UINT ui32,SHORT s1,WORD us1,BYTE b,CHAR sb,SHORT i16,WORD ui16, + LONG64 i64,ULONG64 ui64,FLOAT sgl,DOUBLE d) +{ + pREC->i32 = i32; + pREC->ui32 = ui32; + pREC->s1 = s1; + pREC->us1 = us1; + pREC->b = b; + pREC->sb = sb; + pREC->i16 = i16; + pREC->ui16 = ui16; + pREC->i64 = i64; + pREC->ui64 = ui64; + pREC->sgl = sgl; + pREC->d = d; +} + +bool ValidateS2LPArray(S2 * pREC, S2 * pRECCorrect, int numArrElement) +{ + for(int i = 0; i(int size) + { + T[] array = new T[size]; + + for (int i = 0; i < array.Length; i++) + array[i] = (T)Convert.ChangeType(i, typeof(T)); + + return array; + } + + static TestStruct[] InitStructArray(int size) + { + TestStruct[] array = new TestStruct[size]; + + for (int i = 0; i < array.Length; i++) + { + array[i].x = i; + array[i].d = i; + array[i].l = i; + array[i].str = i.ToString(); + } + + return array; + } + + static bool[] InitBoolArray(int size) + { + bool[] array = new bool[size]; + + for (int i = 0; i < array.Length; i++) + { + if (i % 2 == 0) + array[i] = true; + else + array[i] = false; + } + + return array; + } + + static bool Equals(T[] arr1, T[] arr2) + { + if (arr1 == null && arr2 == null) + return true; + else if (arr1 == null && arr2 != null) + return false; + else if (arr1 != null && arr2 == null) + return false; + else if (arr1.Length != arr2.Length) + return false; + + for (int i = 0; i < arr2.Length; ++i) + { + if (!Object.Equals(arr1[i], arr2[i])) + { + Console.WriteLine("Array marshaling error, when type is {0}", typeof(T)); + Console.WriteLine("Expected: {0}, Actual: {1}", arr1[i], arr2[i]); + return false; + } + } + + return true; + } + + static bool TestStructEquals(TestStruct[] tsArr1, TestStruct[] tsArr2) + { + if (tsArr1 == null && tsArr2 == null) + return true; + else if (tsArr1 == null && tsArr2 != null) + return false; + else if (tsArr1 != null && tsArr2 == null) + return false; + else if (tsArr1.Length != tsArr2.Length) + return false; + + bool result = true; + for (int i = 0; i < tsArr2.Length; i++) + { + result = (tsArr1[i].x == tsArr2[i].x && + tsArr1[i].d == tsArr2[i].d && + tsArr1[i].l == tsArr2[i].l && + tsArr1[i].str == tsArr2[i].str) && result; + } + + return result; + } + + #endregion + + static void RunTest1(string report) + { + Console.WriteLine(report); + + S_INTArray_Seq s1 = new S_INTArray_Seq(); + s1.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeIntArraySeqStructByVal(s1, s1.arr.Length), "TakeIntArraySeqStructByVal"); + + S_UINTArray_Seq s2 = new S_UINTArray_Seq(); + s2.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeUIntArraySeqStructByVal(s2, s2.arr.Length), "TakeUIntArraySeqStructByVal"); + + S_SHORTArray_Seq s3 = new S_SHORTArray_Seq(); + s3.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeShortArraySeqStructByVal(s3, s3.arr.Length), "TakeShortArraySeqStructByVal"); + + S_WORDArray_Seq s4 = new S_WORDArray_Seq(); + s4.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeWordArraySeqStructByVal(s4, s4.arr.Length), "TakeWordArraySeqStructByVal"); + + S_LONG64Array_Seq s5 = new S_LONG64Array_Seq(); + s5.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeLong64ArraySeqStructByVal(s5, s5.arr.Length), "TakeLong64ArraySeqStructByVal"); + + S_ULONG64Array_Seq s6 = new S_ULONG64Array_Seq(); + s6.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeULong64ArraySeqStructByVal(s6, s6.arr.Length), "TakeULong64ArraySeqStructByVal"); + + S_DOUBLEArray_Seq s7 = new S_DOUBLEArray_Seq(); + s7.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeDoubleArraySeqStructByVal(s7, s7.arr.Length), "TakeDoubleArraySeqStructByVal"); + + S_FLOATArray_Seq s8 = new S_FLOATArray_Seq(); + s8.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeFloatArraySeqStructByVal(s8, s8.arr.Length), "TakeFloatArraySeqStructByVal"); + + S_BYTEArray_Seq s9 = new S_BYTEArray_Seq(); + s9.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeByteArraySeqStructByVal(s9, s9.arr.Length), "TakeByteArraySeqStructByVal"); + + S_CHARArray_Seq s10 = new S_CHARArray_Seq(); + s10.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeCharArraySeqStructByVal(s10, s10.arr.Length), "TakeCharArraySeqStructByVal"); + + S_LPSTRArray_Seq s11 = new S_LPSTRArray_Seq(); + s11.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeLPSTRArraySeqStructByVal(s11, s11.arr.Length),"TakeLPSTRArraySeqStructByVal"); + + S_LPCSTRArray_Seq s12 = new S_LPCSTRArray_Seq(); + s12.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeLPCSTRArraySeqStructByVal(s12, s12.arr.Length),"TakeLPCSTRArraySeqStructByVal"); + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + S_BSTRArray_Seq s13 = new S_BSTRArray_Seq(); + s13.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeBSTRArraySeqStructByVal(s13, s13.arr.Length),"TakeBSTRArraySeqStructByVal"); + } + + S_StructArray_Seq s14 = new S_StructArray_Seq(); + s14.arr = InitStructArray(ARRAY_SIZE); + Assert.IsTrue(TakeStructArraySeqStructByVal(s14, s14.arr.Length),"TakeStructArraySeqStructByVal"); + } + + static void RunTest2(string report) + { + Console.WriteLine(report); + + C_INTArray_Seq c1 = new C_INTArray_Seq(); + c1.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeIntArraySeqClassByVal(c1, c1.arr.Length)); + + C_UINTArray_Seq c2 = new C_UINTArray_Seq(); + c2.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeUIntArraySeqClassByVal(c2, c2.arr.Length)); + + C_SHORTArray_Seq c3 = new C_SHORTArray_Seq(); + c3.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeShortArraySeqClassByVal(c3, c3.arr.Length)); + + C_WORDArray_Seq c4 = new C_WORDArray_Seq(); + c4.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeWordArraySeqClassByVal(c4, c4.arr.Length)); + + C_LONG64Array_Seq c5 = new C_LONG64Array_Seq(); + c5.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeLong64ArraySeqClassByVal(c5, c5.arr.Length)); + + C_ULONG64Array_Seq c6 = new C_ULONG64Array_Seq(); + c6.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeULong64ArraySeqClassByVal(c6, c6.arr.Length)); + + C_DOUBLEArray_Seq c7 = new C_DOUBLEArray_Seq(); + c7.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeDoubleArraySeqClassByVal(c7, c7.arr.Length)); + + C_FLOATArray_Seq c8 = new C_FLOATArray_Seq(); + c8.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeFloatArraySeqClassByVal(c8, c8.arr.Length)); + + C_BYTEArray_Seq c9 = new C_BYTEArray_Seq(); + c9.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeByteArraySeqClassByVal(c9, c9.arr.Length)); + + C_CHARArray_Seq c10 = new C_CHARArray_Seq(); + c10.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeCharArraySeqClassByVal(c10, c10.arr.Length)); + + C_LPSTRArray_Seq c11 = new C_LPSTRArray_Seq(); + c11.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeLPSTRArraySeqClassByVal(c11, c11.arr.Length)); + + C_LPCSTRArray_Seq c12 = new C_LPCSTRArray_Seq(); + c12.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeLPCSTRArraySeqClassByVal(c12, c12.arr.Length)); + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + C_BSTRArray_Seq c13 = new C_BSTRArray_Seq(); + c13.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeBSTRArraySeqClassByVal(c13, c13.arr.Length)); + } + + C_StructArray_Seq c14 = new C_StructArray_Seq(); + c14.arr = InitStructArray(ARRAY_SIZE); + Assert.IsTrue(TakeStructArraySeqClassByVal(c14, c14.arr.Length)); + } + + static void RunTest3(string report) + { + Console.WriteLine(report); + + S_INTArray_Exp s1 = new S_INTArray_Exp(); + s1.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeIntArrayExpStructByVal(s1, s1.arr.Length), "TakeIntArrayExpStructByVal"); + + S_UINTArray_Exp s2 = new S_UINTArray_Exp(); + s2.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeUIntArrayExpStructByVal(s2, s2.arr.Length), "TakeUIntArrayExpStructByVal"); + + S_SHORTArray_Exp s3 = new S_SHORTArray_Exp(); + s3.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeShortArrayExpStructByVal(s3, s3.arr.Length), "TakeShortArrayExpStructByVal"); + + S_WORDArray_Exp s4 = new S_WORDArray_Exp(); + s4.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeWordArrayExpStructByVal(s4, s4.arr.Length), "TakeWordArrayExpStructByVal"); + + S_LONG64Array_Exp s5 = new S_LONG64Array_Exp(); + s5.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeLong64ArrayExpStructByVal(s5, s5.arr.Length), "TakeLong64ArrayExpStructByVal"); + + S_ULONG64Array_Exp s6 = new S_ULONG64Array_Exp(); + s6.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeULong64ArrayExpStructByVal(s6, s6.arr.Length), "TakeULong64ArrayExpStructByVal"); + + S_DOUBLEArray_Exp s7 = new S_DOUBLEArray_Exp(); + s7.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeDoubleArrayExpStructByVal(s7, s7.arr.Length), "TakeDoubleArrayExpStructByVal"); + + S_FLOATArray_Exp s8 = new S_FLOATArray_Exp(); + s8.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeFloatArrayExpStructByVal(s8, s8.arr.Length), "TakeFloatArrayExpStructByVal"); + + S_BYTEArray_Exp s9 = new S_BYTEArray_Exp(); + s9.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeByteArrayExpStructByVal(s9, s9.arr.Length), "TakeByteArrayExpStructByVal"); + + S_CHARArray_Exp s10 = new S_CHARArray_Exp(); + s10.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeCharArrayExpStructByVal(s10, s10.arr.Length), "TakeCharArrayExpStructByVal"); + + S_LPSTRArray_Exp s11 = new S_LPSTRArray_Exp(); + s11.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeLPSTRArrayExpStructByVal(s11, s11.arr.Length)); + + S_LPCSTRArray_Exp s12 = new S_LPCSTRArray_Exp(); + s12.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeLPCSTRArrayExpStructByVal(s12, s12.arr.Length)); + + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + S_BSTRArray_Exp c13 = new S_BSTRArray_Exp(); + c13.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeBSTRArrayExpStructByVal(c13, c13.arr.Length)); + } + + S_StructArray_Exp s14 = new S_StructArray_Exp(); + s14.arr = InitStructArray(ARRAY_SIZE); + Assert.IsTrue(TakeStructArrayExpStructByVal(s14, s14.arr.Length)); + } + + static void RunTest4(string report) + { + Console.WriteLine(report); + + C_INTArray_Exp c1 = new C_INTArray_Exp(); + c1.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeIntArrayExpClassByVal(c1, c1.arr.Length)); + + C_UINTArray_Exp c2 = new C_UINTArray_Exp(); + c2.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeUIntArrayExpClassByVal(c2, c2.arr.Length)); + + C_SHORTArray_Exp c3 = new C_SHORTArray_Exp(); + c3.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeShortArrayExpClassByVal(c3, c3.arr.Length)); + + C_WORDArray_Exp c4 = new C_WORDArray_Exp(); + c4.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeWordArrayExpClassByVal(c4, c4.arr.Length)); + + C_LONG64Array_Exp c5 = new C_LONG64Array_Exp(); + c5.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeLong64ArrayExpClassByVal(c5, c5.arr.Length)); + + C_ULONG64Array_Exp c6 = new C_ULONG64Array_Exp(); + c6.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeULong64ArrayExpClassByVal(c6, c6.arr.Length)); + + C_DOUBLEArray_Exp c7 = new C_DOUBLEArray_Exp(); + c7.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeDoubleArrayExpClassByVal(c7, c7.arr.Length)); + + C_FLOATArray_Exp c8 = new C_FLOATArray_Exp(); + c8.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeFloatArrayExpClassByVal(c8, c8.arr.Length)); + + C_BYTEArray_Exp c9 = new C_BYTEArray_Exp(); + c9.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeByteArrayExpClassByVal(c9, c9.arr.Length)); + + C_CHARArray_Exp c10 = new C_CHARArray_Exp(); + c10.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeCharArrayExpClassByVal(c10, c10.arr.Length)); + + C_LPSTRArray_Exp c11 = new C_LPSTRArray_Exp(); + c11.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeLPSTRArrayExpClassByVal(c11, c11.arr.Length)); + + C_LPCSTRArray_Exp c12 = new C_LPCSTRArray_Exp(); + c12.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeLPCSTRArrayExpClassByVal(c12, c12.arr.Length)); + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + C_BSTRArray_Exp c13 = new C_BSTRArray_Exp(); + c13.arr = InitArray(ARRAY_SIZE); + Assert.IsTrue(TakeBSTRArrayExpClassByVal(c13, c13.arr.Length)); + } + + C_StructArray_Exp c14 = new C_StructArray_Exp(); + c14.arr = InitStructArray(ARRAY_SIZE); + Assert.IsTrue(TakeStructArrayExpClassByVal(c14, c14.arr.Length)); + } + + static void RunTest5(string report) + { + Console.WriteLine(report); + + C_INTArray_Seq retval1 = S_INTArray_Ret(); + Assert.IsTrue(Equals(InitArray(ARRAY_SIZE), retval1.arr)); + + C_UINTArray_Seq retval2 = S_UINTArray_Ret(); + Assert.IsTrue(Equals(InitArray(ARRAY_SIZE), retval2.arr)); + + C_SHORTArray_Seq retval3 = S_SHORTArray_Ret(); + Assert.IsTrue(Equals(InitArray(ARRAY_SIZE), retval3.arr)); + + C_WORDArray_Seq retval4 = S_WORDArray_Ret(); + Assert.IsTrue(Equals(InitArray(ARRAY_SIZE), retval4.arr)); + + C_LONG64Array_Seq retval5 = S_LONG64Array_Ret(); + Assert.IsTrue(Equals(InitArray(ARRAY_SIZE), retval5.arr)); + + C_ULONG64Array_Seq retval6 = S_ULONG64Array_Ret(); + Assert.IsTrue(Equals(InitArray(ARRAY_SIZE), retval6.arr)); + + C_DOUBLEArray_Seq retval7 = S_DOUBLEArray_Ret(); + Assert.IsTrue(Equals(InitArray(ARRAY_SIZE), retval7.arr)); + + C_FLOATArray_Seq retval8 = S_FLOATArray_Ret(); + Assert.IsTrue(Equals(InitArray(ARRAY_SIZE), retval8.arr)); + + C_BYTEArray_Seq retval9 = S_BYTEArray_Ret(); + Assert.IsTrue(Equals(InitArray(ARRAY_SIZE), retval9.arr)); + + C_CHARArray_Seq retval10 = S_CHARArray_Ret(); + Assert.IsTrue(Equals(InitArray(ARRAY_SIZE), retval10.arr)); + + C_LPSTRArray_Seq retval11 = S_LPSTRArray_Ret(); + Assert.IsTrue(Equals(InitArray(ARRAY_SIZE), retval11.arr)); + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + C_BSTRArray_Seq retval12 = S_BSTRArray_Ret(); + Assert.IsTrue(Equals(InitArray(ARRAY_SIZE), retval12.arr)); + } + + C_StructArray_Seq retval13 = S_StructArray_Ret(); + Assert.IsTrue(TestStructEquals(InitStructArray(ARRAY_SIZE), retval13.arr)); + } + + static void RunTest6(string report) + { + Console.WriteLine(report); + + C_INTArray_Exp retval1 = S_INTArray_Ret2(); + Assert.IsTrue(Equals(InitArray(ARRAY_SIZE), retval1.arr)); + + C_UINTArray_Exp retval2 = S_UINTArray_Ret2(); + Assert.IsTrue(Equals(InitArray(ARRAY_SIZE), retval2.arr)); + + C_SHORTArray_Exp retval3 = S_SHORTArray_Ret2(); + Assert.IsTrue(Equals(InitArray(ARRAY_SIZE), retval3.arr)); + + C_WORDArray_Exp retval4 = S_WORDArray_Ret2(); + Assert.IsTrue(Equals(InitArray(ARRAY_SIZE), retval4.arr)); + + C_LONG64Array_Exp retval5 = S_LONG64Array_Ret2(); + Assert.IsTrue(Equals(InitArray(ARRAY_SIZE), retval5.arr)); + + C_ULONG64Array_Exp retval6 = S_ULONG64Array_Ret2(); + Assert.IsTrue(Equals(InitArray(ARRAY_SIZE), retval6.arr)); + + C_DOUBLEArray_Exp retval7 = S_DOUBLEArray_Ret2(); + Assert.IsTrue(Equals(InitArray(ARRAY_SIZE), retval7.arr)); + + C_FLOATArray_Exp retval8 = S_FLOATArray_Ret2(); + Assert.IsTrue(Equals(InitArray(ARRAY_SIZE), retval8.arr)); + + C_BYTEArray_Exp retval9 = S_BYTEArray_Ret2(); + Assert.IsTrue(Equals(InitArray(ARRAY_SIZE), retval9.arr)); + + C_CHARArray_Exp retval10 = S_CHARArray_Ret2(); + Assert.IsTrue(Equals(InitArray(ARRAY_SIZE), retval10.arr)); + + C_LPSTRArray_Exp retval11 = S_LPSTRArray_Ret2(); + Assert.IsTrue(Equals(InitArray(ARRAY_SIZE), retval11.arr)); + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + C_BSTRArray_Exp retval12 = S_BSTRArray_Ret2(); + Assert.IsTrue(Equals(InitArray(ARRAY_SIZE), retval12.arr)); + } + + C_StructArray_Exp retval13 = S_StructArray_Ret2(); + Assert.IsTrue(TestStructEquals(InitStructArray(ARRAY_SIZE), retval13.arr)); + } + + static int Main(string[] args) + { + try + { + RunTest1("RunTest1 : Marshal array as field as ByValArray in sequential struct as parameter."); + RunTest2("RunTest2 : Marshal array as field as ByValArray in sequential class as parameter."); + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + RunTest3("RunTest3 : Marshal array as field as ByValArray in explicit struct as parameter."); + } + RunTest4("RunTest4 : Marshal array as field as ByValArray in explicit class as parameter."); + RunTest5("RunTest5 : Marshal array as field as ByValArray in sequential class as return type."); + RunTest6("RunTest6 : Marshal array as field as ByValArray in explicit class as return type."); + + Console.WriteLine("\nTest PASS."); + return 100; + } + catch (Exception e) + { + Console.WriteLine($"\nTEST FAIL: {e.Message}"); + return 101; + } + } +} diff --git a/tests/src/Interop/PInvoke/Array/MarshalArrayAsField/AsByValArray/AsByValArrayTest.csproj b/tests/src/Interop/PInvoke/Array/MarshalArrayAsField/AsByValArray/AsByValArrayTest.csproj new file mode 100644 index 0000000..3ebd652 --- /dev/null +++ b/tests/src/Interop/PInvoke/Array/MarshalArrayAsField/AsByValArray/AsByValArrayTest.csproj @@ -0,0 +1,34 @@ + + + + + Debug + AnyCPU + AsByValArrayTest + 2.0 + {F1E66554-8C8E-4141-85CF-D0CD6A0CD0B0} + Exe + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + ..\..\..\..\ + $(DefineConstants);STATIC + + + + + + + False + + + + + + + + + + + + + + diff --git a/tests/src/Interop/PInvoke/Array/MarshalArrayAsField/AsByValArray/FldDef_DefaultArray.cs b/tests/src/Interop/PInvoke/Array/MarshalArrayAsField/AsByValArray/FldDef_DefaultArray.cs new file mode 100644 index 0000000..d6c84b4 --- /dev/null +++ b/tests/src/Interop/PInvoke/Array/MarshalArrayAsField/AsByValArray/FldDef_DefaultArray.cs @@ -0,0 +1,189 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; + +#pragma warning disable 618 + +#region Struct Definition +[StructLayout(LayoutKind.Sequential)] +public struct S2 +{ + public int i32; + public uint ui32; + public short s1; + public ushort us1; + public Byte b; + public SByte sb; + public Int16 i16; + public UInt16 ui16; + public Int64 i64; + public UInt64 ui64; + public Single sgl; + public Double d; +} + +[StructLayout(LayoutKind.Sequential)] +public struct Struct_Sequential +{ + public int[] longArr; + + public uint[] ulongArr; + + public short[] shortArr; + + public ushort[] ushortArr; + + public long[] long64Arr; + + public ulong[] ulong64Arr; + + public double[] doubleArr; + + public float[] floatArr; + + public byte[] byteArr; + + //not default + //helper field definition, just match structure member verification func on C++ side + [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)] + public string[] bstrArr; + + public bool[] boolArr; +} + +[StructLayout(LayoutKind.Explicit)] +public struct Struct_Explicit +{ + [FieldOffset(0 * 8)] + public int[] longArr; + + [FieldOffset(1 * 8)] + public uint[] ulongArr; + + [FieldOffset(2 * 8)] + public short[] shortArr; + + [FieldOffset(3 * 8)] + public ushort[] ushortArr; + + [FieldOffset(4 * 8)] + public long[] long64Arr; + + [FieldOffset(5 * 8)] + public ulong[] ulong64Arr; + + [FieldOffset(6 * 8)] + public double[] doubleArr; + + [FieldOffset(7 * 8)] + public float[] floatArr; + + [FieldOffset(8 * 8)] + public byte[] byteArr; + + [FieldOffset(9 * 8)] + [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)] + public string[] bstrArr; + + [FieldOffset(10 * 8)] + public bool[] boolArr; +} + +[StructLayout(LayoutKind.Sequential)] +public struct Struct_SeqWithArrOfStr +{ + public S2[] arrS2; +} + +[StructLayout(LayoutKind.Explicit)] +public struct Struct_ExpWithArrOfStr +{ + [FieldOffset(0)] + public S2[] arrS2; +} +#endregion + +#region Class Definition +[StructLayout(LayoutKind.Sequential)] +public class Class_Sequential +{ + public int[] longArr; + + public uint[] ulongArr; + + public short[] shortArr; + + public ushort[] ushortArr; + + public long[] long64Arr; + + public ulong[] ulong64Arr; + + public double[] doubleArr; + + public float[] floatArr; + + public byte[] byteArr; + + [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)] + public string[] bstrArr; + + public bool[] boolArr; +} + +[StructLayout(LayoutKind.Explicit)] +public class Class_Explicit +{ + [FieldOffset(0 * 8)] + public int[] longArr; + + [FieldOffset(1 * 8)] + public uint[] ulongArr; + + [FieldOffset(2 * 8)] + public short[] shortArr; + + [FieldOffset(3 * 8)] + public ushort[] ushortArr; + + [FieldOffset(4 * 8)] + public long[] long64Arr; + + [FieldOffset(5 * 8)] + public ulong[] ulong64Arr; + + [FieldOffset(6 * 8)] + public double[] doubleArr; + + [FieldOffset(7 * 8)] + public float[] floatArr; + + [FieldOffset(8 * 8)] + public byte[] byteArr; + + [FieldOffset(9 * 8)] + [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)] + public string[] bstrArr; + + [FieldOffset(10 * 8)] + public bool[] boolArr; +} + +[StructLayout(LayoutKind.Sequential)] +public class Class_SeqWithArrOfStr +{ + public S2[] arrS2; +} + +[StructLayout(LayoutKind.Explicit)] +public class Class_ExpWithArrOfStr +{ + [FieldOffset(0)] + public S2[] arrS2; +} +#endregion + +#pragma warning restore 618 \ No newline at end of file diff --git a/tests/src/Interop/PInvoke/Array/MarshalArrayAsField/AsLPArray/AsLPArrayTest.cs b/tests/src/Interop/PInvoke/Array/MarshalArrayAsField/AsLPArray/AsLPArrayTest.cs new file mode 100644 index 0000000..93404e8 --- /dev/null +++ b/tests/src/Interop/PInvoke/Array/MarshalArrayAsField/AsLPArray/AsLPArrayTest.cs @@ -0,0 +1,445 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; +using TestLibrary; + +class Test +{ + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeIntArraySeqStructByVal([In]S_INTArray_Seq s, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeUIntArraySeqStructByVal([In]S_UINTArray_Seq s, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeShortArraySeqStructByVal([In]S_SHORTArray_Seq s, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeWordArraySeqStructByVal([In]S_WORDArray_Seq s, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeLong64ArraySeqStructByVal([In]S_LONG64Array_Seq s, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeULong64ArraySeqStructByVal([In]S_ULONG64Array_Seq s, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeDoubleArraySeqStructByVal([In]S_DOUBLEArray_Seq s, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeFloatArraySeqStructByVal([In]S_FLOATArray_Seq s, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeByteArraySeqStructByVal([In]S_BYTEArray_Seq s, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeCharArraySeqStructByVal([In]S_CHARArray_Seq s, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeLPSTRArraySeqStructByVal([In]S_LPSTRArray_Seq s, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeLPCSTRArraySeqStructByVal([In]S_LPCSTRArray_Seq s, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeBSTRArraySeqStructByVal([In]S_BSTRArray_Seq s, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeStructArraySeqStructByVal([In]S_StructArray_Seq s, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeIntArraySeqClassByVal([In]C_INTArray_Seq c, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeUIntArraySeqClassByVal([In]C_UINTArray_Seq c, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeShortArraySeqClassByVal([In]C_SHORTArray_Seq c, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeWordArraySeqClassByVal([In]C_WORDArray_Seq c, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeLong64ArraySeqClassByVal([In]C_LONG64Array_Seq c, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeULong64ArraySeqClassByVal([In]C_ULONG64Array_Seq c, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeDoubleArraySeqClassByVal([In]C_DOUBLEArray_Seq c, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeFloatArraySeqClassByVal([In]C_FLOATArray_Seq c, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeByteArraySeqClassByVal([In]C_BYTEArray_Seq c, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeCharArraySeqClassByVal([In]C_CHARArray_Seq c, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeLPSTRArraySeqClassByVal([In]C_LPSTRArray_Seq c, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeLPCSTRArraySeqClassByVal([In]C_LPCSTRArray_Seq c, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeBSTRArraySeqClassByVal([In]C_BSTRArray_Seq c, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeStructArraySeqClassByVal([In]C_StructArray_Seq c, [In]int size); + + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeIntArrayExpStructByVal([In]S_INTArray_Exp s, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeUIntArrayExpStructByVal([In]S_UINTArray_Exp s, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeShortArrayExpStructByVal([In]S_SHORTArray_Exp s, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeWordArrayExpStructByVal([In]S_WORDArray_Exp s, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeLong64ArrayExpStructByVal([In]S_LONG64Array_Exp s, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeULong64ArrayExpStructByVal([In]S_ULONG64Array_Exp s, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeDoubleArrayExpStructByVal([In]S_DOUBLEArray_Exp s, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeFloatArrayExpStructByVal([In]S_FLOATArray_Exp s, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeByteArrayExpStructByVal([In]S_BYTEArray_Exp s, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeCharArrayExpStructByVal([In]S_CHARArray_Exp s, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeLPSTRArrayExpStructByVal([In]S_LPSTRArray_Exp s, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeLPCSTRArrayExpStructByVal([In]S_LPCSTRArray_Exp s, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeBSTRArrayExpStructByVal([In]S_BSTRArray_Exp s, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeStructArrayExpStructByVal([In]S_StructArray_Exp s, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeIntArrayExpClassByVal([In]C_INTArray_Exp c, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeUIntArrayExpClassByVal([In]C_UINTArray_Exp c, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeShortArrayExpClassByVal([In]C_SHORTArray_Exp c, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeWordArrayExpClassByVal([In]C_WORDArray_Exp c, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeLong64ArrayExpClassByVal([In]C_LONG64Array_Exp c, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeULong64ArrayExpClassByVal([In]C_ULONG64Array_Exp c, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeDoubleArrayExpClassByVal([In]C_DOUBLEArray_Exp c, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeFloatArrayExpClassByVal([In]C_FLOATArray_Exp c, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeByteArrayExpClassByVal([In]C_BYTEArray_Exp c, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeCharArrayExpClassByVal([In]C_CHARArray_Exp c, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeLPSTRArrayExpClassByVal([In]C_LPSTRArray_Exp c, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeLPCSTRArrayExpClassByVal([In]C_LPCSTRArray_Exp c, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeBSTRArrayExpClassByVal([In]C_BSTRArray_Exp c, [In]int size); + [DllImport("MarshalArrayByValArrayNative", CallingConvention = CallingConvention.Cdecl)] + static extern bool TakeStructArrayExpClassByVal([In]C_StructArray_Exp c, [In]int size); + + #region Helper + + internal const int ARRAY_SIZE = 100; + + static T[] InitArray(int size) + { + T[] array = new T[size]; + + for (int i = 0; i < array.Length; i++) + array[i] = (T)Convert.ChangeType(i, typeof(T)); + + return array; + } + + static TestStruct[] InitStructArray(int size) + { + TestStruct[] array = new TestStruct[size]; + + for (int i = 0; i < array.Length; i++) + { + array[i].x = i; + array[i].d = i; + array[i].l = i; + array[i].str = i.ToString(); + } + + return array; + } + + static bool[] InitBoolArray(int size) + { + bool[] array = new bool[size]; + + for (int i = 0; i < array.Length; i++) + { + if (i % 2 == 0) + array[i] = true; + else + array[i] = false; + } + + return array; + } + + #endregion + + static void RunTest1(string report) + { + Console.WriteLine(report); + S_INTArray_Seq s1 = new S_INTArray_Seq(); + s1.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeIntArraySeqStructByVal(s1, ARRAY_SIZE), "TakeIntArraySeqStructByVal"); + + S_UINTArray_Seq s2 = new S_UINTArray_Seq(); + s2.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeUIntArraySeqStructByVal(s2, ARRAY_SIZE), "TakeUIntArraySeqStructByVal"); + + S_SHORTArray_Seq s3 = new S_SHORTArray_Seq(); + s3.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeShortArraySeqStructByVal(s3, ARRAY_SIZE), "TakeShortArraySeqStructByVal"); + + S_WORDArray_Seq s4 = new S_WORDArray_Seq(); + s4.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeWordArraySeqStructByVal(s4, ARRAY_SIZE), "TakeWordArraySeqStructByVal"); + + S_LONG64Array_Seq s5 = new S_LONG64Array_Seq(); + s5.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeLong64ArraySeqStructByVal(s5, ARRAY_SIZE), "TakeLong64ArraySeqStructByVal"); + + S_ULONG64Array_Seq s6 = new S_ULONG64Array_Seq(); + s6.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeULong64ArraySeqStructByVal(s6, ARRAY_SIZE), "TakeULong64ArraySeqStructByVal"); + + S_DOUBLEArray_Seq s7 = new S_DOUBLEArray_Seq(); + s7.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeDoubleArraySeqStructByVal(s7, ARRAY_SIZE), "TakeDoubleArraySeqStructByVal"); + + S_FLOATArray_Seq s8 = new S_FLOATArray_Seq(); + s8.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeFloatArraySeqStructByVal(s8, ARRAY_SIZE), "TakeFloatArraySeqStructByVal"); + + S_BYTEArray_Seq s9 = new S_BYTEArray_Seq(); + s9.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeByteArraySeqStructByVal(s9, ARRAY_SIZE), "TakeByteArraySeqStructByVal"); + + S_CHARArray_Seq s10 = new S_CHARArray_Seq(); + s10.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeCharArraySeqStructByVal(s10, ARRAY_SIZE), "TakeCharArraySeqStructByVal"); + + S_LPSTRArray_Seq s11 = new S_LPSTRArray_Seq(); + s11.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeLPSTRArraySeqStructByVal(s11, ARRAY_SIZE), "TakeLPSTRArraySeqStructByVal"); + + S_LPCSTRArray_Seq s12 = new S_LPCSTRArray_Seq(); + s12.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeLPCSTRArraySeqStructByVal(s12, ARRAY_SIZE), "TakeLPCSTRArraySeqStructByVal"); + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + S_BSTRArray_Seq s13 = new S_BSTRArray_Seq(); + s13.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeBSTRArraySeqStructByVal(s13, ARRAY_SIZE), "TakeBSTRArraySeqStructByVal"); + } + + S_StructArray_Seq s14 = new S_StructArray_Seq(); + s14.arr = InitStructArray(ARRAY_SIZE); + Assert.Throws(() => TakeStructArraySeqStructByVal(s14, ARRAY_SIZE), "TakeStructArraySeqStructByVal"); + } + + static void RunTest2(string report) + { + Console.WriteLine(report); + C_INTArray_Seq c1 = new C_INTArray_Seq(); + c1.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeIntArraySeqClassByVal(c1, ARRAY_SIZE), "TakeIntArraySeqClassByVal"); + + C_UINTArray_Seq c2 = new C_UINTArray_Seq(); + c2.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeUIntArraySeqClassByVal(c2, ARRAY_SIZE), "TakeUIntArraySeqClassByVal"); + + C_SHORTArray_Seq c3 = new C_SHORTArray_Seq(); + c3.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeShortArraySeqClassByVal(c3, ARRAY_SIZE), "TakeShortArraySeqClassByVal"); + + C_WORDArray_Seq c4 = new C_WORDArray_Seq(); + c4.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeWordArraySeqClassByVal(c4, ARRAY_SIZE), "TakeWordArraySeqClassByVal"); + + C_LONG64Array_Seq c5 = new C_LONG64Array_Seq(); + c5.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeLong64ArraySeqClassByVal(c5, ARRAY_SIZE), "TakeLong64ArraySeqClassByVal"); + + C_ULONG64Array_Seq c6 = new C_ULONG64Array_Seq(); + c6.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeULong64ArraySeqClassByVal(c6, ARRAY_SIZE), "TakeULong64ArraySeqClassByVal"); + + C_DOUBLEArray_Seq c7 = new C_DOUBLEArray_Seq(); + c7.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeDoubleArraySeqClassByVal(c7, ARRAY_SIZE), "TakeDoubleArraySeqClassByVal"); + + C_FLOATArray_Seq c8 = new C_FLOATArray_Seq(); + c8.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeFloatArraySeqClassByVal(c8, ARRAY_SIZE), "TakeFloatArraySeqClassByVal"); + + C_BYTEArray_Seq c9 = new C_BYTEArray_Seq(); + c9.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeByteArraySeqClassByVal(c9, ARRAY_SIZE), "TakeByteArraySeqClassByVal"); + + C_CHARArray_Seq c10 = new C_CHARArray_Seq(); + c10.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeCharArraySeqClassByVal(c10, ARRAY_SIZE), "TakeCharArraySeqClassByVal"); + + C_LPSTRArray_Seq c11 = new C_LPSTRArray_Seq(); + c11.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeLPSTRArraySeqClassByVal(c11, ARRAY_SIZE), "TakeLPSTRArraySeqClassByVal"); + + C_LPCSTRArray_Seq c12 = new C_LPCSTRArray_Seq(); + c12.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeLPCSTRArraySeqClassByVal(c12, ARRAY_SIZE), "TakeLPCSTRArraySeqClassByVal"); + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + C_BSTRArray_Seq c13 = new C_BSTRArray_Seq(); + c13.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeBSTRArraySeqClassByVal(c13, ARRAY_SIZE), "TakeBSTRArraySeqClassByVal"); + } + + C_StructArray_Seq c14 = new C_StructArray_Seq(); + c14.arr = InitStructArray(ARRAY_SIZE); + Assert.Throws(() => TakeStructArraySeqClassByVal(c14, ARRAY_SIZE), "TakeStructArraySeqClassByVal"); + } + + static void RunTest3(string report) + { + Console.WriteLine(report); + + S_INTArray_Exp s1 = new S_INTArray_Exp(); + s1.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeIntArrayExpStructByVal(s1, ARRAY_SIZE), "TakeIntArrayExpStructByVal"); + + S_UINTArray_Exp s2 = new S_UINTArray_Exp(); + s2.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeUIntArrayExpStructByVal(s2, ARRAY_SIZE), "TakeUIntArrayExpStructByVal"); + + S_SHORTArray_Exp s3 = new S_SHORTArray_Exp(); + s3.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeShortArrayExpStructByVal(s3, ARRAY_SIZE), "TakeShortArrayExpStructByVal"); + + S_WORDArray_Exp s4 = new S_WORDArray_Exp(); + s4.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeWordArrayExpStructByVal(s4, ARRAY_SIZE), "TakeWordArrayExpStructByVal"); + + S_LONG64Array_Exp s5 = new S_LONG64Array_Exp(); + s5.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeLong64ArrayExpStructByVal(s5, ARRAY_SIZE), "TakeLong64ArrayExpStructByVal"); + + S_ULONG64Array_Exp s6 = new S_ULONG64Array_Exp(); + s6.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeULong64ArrayExpStructByVal(s6, ARRAY_SIZE), "TakeULong64ArrayExpStructByVal"); + + S_DOUBLEArray_Exp s7 = new S_DOUBLEArray_Exp(); + s7.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeDoubleArrayExpStructByVal(s7, ARRAY_SIZE), "TakeDoubleArrayExpStructByVal"); + + S_FLOATArray_Exp s8 = new S_FLOATArray_Exp(); + s8.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeFloatArrayExpStructByVal(s8, ARRAY_SIZE), "TakeFloatArrayExpStructByVal"); + + S_BYTEArray_Exp s9 = new S_BYTEArray_Exp(); + s9.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeByteArrayExpStructByVal(s9, ARRAY_SIZE), "TakeByteArrayExpStructByVal"); + + S_CHARArray_Exp s10 = new S_CHARArray_Exp(); + s10.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeCharArrayExpStructByVal(s10, ARRAY_SIZE), "TakeCharArrayExpStructByVal"); + + S_LPSTRArray_Exp s11 = new S_LPSTRArray_Exp(); + s11.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeLPSTRArrayExpStructByVal(s11, ARRAY_SIZE), "TakeLPSTRArrayExpStructByVal"); + + S_LPCSTRArray_Exp s12 = new S_LPCSTRArray_Exp(); + s12.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeLPCSTRArrayExpStructByVal(s12, ARRAY_SIZE), "TakeLPCSTRArrayExpStructByVal"); + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + S_BSTRArray_Exp s13 = new S_BSTRArray_Exp(); + s13.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeBSTRArrayExpStructByVal(s13, ARRAY_SIZE), "TakeBSTRArrayExpStructByVal"); + } + + S_StructArray_Exp s14 = new S_StructArray_Exp(); + s14.arr = InitStructArray(ARRAY_SIZE); + Assert.Throws(() => TakeStructArrayExpStructByVal(s14, ARRAY_SIZE), "TakeStructArrayExpStructByVal"); + } + + static void RunTest4(string report) + { + Console.WriteLine(report); + + C_INTArray_Exp c1 = new C_INTArray_Exp(); + c1.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeIntArrayExpClassByVal(c1, ARRAY_SIZE), "TakeIntArrayExpClassByVal"); + + C_UINTArray_Exp c2 = new C_UINTArray_Exp(); + c2.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeUIntArrayExpClassByVal(c2, ARRAY_SIZE), "TakeUIntArrayExpClassByVal"); + + C_SHORTArray_Exp c3 = new C_SHORTArray_Exp(); + c3.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeShortArrayExpClassByVal(c3, ARRAY_SIZE), "TakeShortArrayExpClassByVal"); + + C_WORDArray_Exp c4 = new C_WORDArray_Exp(); + c4.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeWordArrayExpClassByVal(c4, ARRAY_SIZE), "TakeWordArrayExpClassByVal"); + + C_LONG64Array_Exp c5 = new C_LONG64Array_Exp(); + c5.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeLong64ArrayExpClassByVal(c5, ARRAY_SIZE), "TakeLong64ArrayExpClassByVal"); + + C_ULONG64Array_Exp c6 = new C_ULONG64Array_Exp(); + c6.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeULong64ArrayExpClassByVal(c6, ARRAY_SIZE), "TakeULong64ArrayExpClassByVal"); + + C_DOUBLEArray_Exp c7 = new C_DOUBLEArray_Exp(); + c7.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeDoubleArrayExpClassByVal(c7, ARRAY_SIZE), "TakeDoubleArrayExpClassByVal"); + + C_FLOATArray_Exp c8 = new C_FLOATArray_Exp(); + c8.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeFloatArrayExpClassByVal(c8, ARRAY_SIZE), "TakeFloatArrayExpClassByVal"); + + C_BYTEArray_Exp c9 = new C_BYTEArray_Exp(); + c9.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeByteArrayExpClassByVal(c9, ARRAY_SIZE), "TakeByteArrayExpClassByVal"); + + C_CHARArray_Exp c10 = new C_CHARArray_Exp(); + c10.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeCharArrayExpClassByVal(c10, ARRAY_SIZE), "TakeCharArrayExpClassByVal"); + + C_LPSTRArray_Exp c11 = new C_LPSTRArray_Exp(); + c11.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeLPSTRArrayExpClassByVal(c11, ARRAY_SIZE), "TakeLPSTRArrayExpClassByVal"); + + C_LPCSTRArray_Exp c12 = new C_LPCSTRArray_Exp(); + c12.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeLPCSTRArrayExpClassByVal(c12, ARRAY_SIZE), "TakeLPCSTRArrayExpClassByVal"); + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + C_BSTRArray_Exp c13 = new C_BSTRArray_Exp(); + c13.arr = InitArray(ARRAY_SIZE); + Assert.Throws(() => TakeBSTRArrayExpClassByVal(c13, ARRAY_SIZE), "TakeBSTRArrayExpClassByVal"); + } + + C_StructArray_Exp c14 = new C_StructArray_Exp(); + c14.arr = InitStructArray(ARRAY_SIZE); + Assert.Throws(() => TakeStructArrayExpClassByVal(c14, ARRAY_SIZE), "TakeStructArrayExpClassByVal"); + } + + static int Main(string[] args) + { + try + { + RunTest1("RunTest 1 : Marshal Array In Sequential Struct As LPArray. "); + RunTest2("RunTest 2 : Marshal Array In Sequential Class As LPArray. "); + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + RunTest3("RunTest 3 : Marshal Array In Explicit Struct As LPArray. "); + } + RunTest4("RunTest 4 : Marshal Array In Explicit Class As LPArray. "); + Console.WriteLine("\nTest PASS."); + return 100; + } + catch (Exception e) + { + Console.WriteLine($"\nTest FAIL: {e}"); + return 101; + } + } +} diff --git a/tests/src/Interop/PInvoke/Array/MarshalArrayAsField/AsLPArray/AsLPArrayTest.csproj b/tests/src/Interop/PInvoke/Array/MarshalArrayAsField/AsLPArray/AsLPArrayTest.csproj new file mode 100644 index 0000000..47dec3c --- /dev/null +++ b/tests/src/Interop/PInvoke/Array/MarshalArrayAsField/AsLPArray/AsLPArrayTest.csproj @@ -0,0 +1,34 @@ + + + + + Debug + AnyCPU + AsLPArrayTest + 2.0 + {F1E66554-8C8E-4141-85CF-D0CD6A0CD0B0} + Exe + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + ..\..\..\..\ + $(DefineConstants);STATIC + + + + + + + False + + + + + + + + + + + + + + diff --git a/tests/src/Interop/PInvoke/Array/MarshalArrayAsField/AsLPArray/FldDef_LPArray.cs b/tests/src/Interop/PInvoke/Array/MarshalArrayAsField/AsLPArray/FldDef_LPArray.cs new file mode 100644 index 0000000..d1bd019 --- /dev/null +++ b/tests/src/Interop/PInvoke/Array/MarshalArrayAsField/AsLPArray/FldDef_LPArray.cs @@ -0,0 +1,483 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; + +#region Sequential +#region sequential stuct definition +[StructLayout(LayoutKind.Sequential)] +public struct S_INTArray_Seq +{ + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public int[] arr; +} + +[StructLayout(LayoutKind.Sequential)] +public struct S_UINTArray_Seq +{ + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public uint[] arr; +} + +[StructLayout(LayoutKind.Sequential)] +public struct S_SHORTArray_Seq +{ + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public short[] arr; +} + +[StructLayout(LayoutKind.Sequential)] +public struct S_WORDArray_Seq +{ + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public ushort[] arr; +} + +[StructLayout(LayoutKind.Sequential)] +public struct S_LONG64Array_Seq +{ + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public long[] arr; +} + +[StructLayout(LayoutKind.Sequential)] +public struct S_ULONG64Array_Seq +{ + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public ulong[] arr; +} + +[StructLayout(LayoutKind.Sequential)] +public struct S_DOUBLEArray_Seq +{ + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public double[] arr; +} + +[StructLayout(LayoutKind.Sequential)] +public struct S_FLOATArray_Seq +{ + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public float[] arr; +} + +[StructLayout(LayoutKind.Sequential)] +public struct S_BYTEArray_Seq +{ + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public byte[] arr; +} + +[StructLayout(LayoutKind.Sequential)] +public struct S_CHARArray_Seq +{ + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public char[] arr; +} + +[StructLayout(LayoutKind.Sequential)] +public struct S_LPSTRArray_Seq +{ + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public string[] arr; +} + +[StructLayout(LayoutKind.Sequential)] +public struct S_LPCSTRArray_Seq +{ + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public string[] arr; +} + +[StructLayout(LayoutKind.Sequential)] +public struct S_BSTRArray_Seq +{ + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE, ArraySubType = UnmanagedType.BStr)] + public string[] arr; +} + +//struct array in a struct +[StructLayout(LayoutKind.Sequential)] +public struct TestStruct +{ + public int x; + public double d; + public long l; + public string str; +} + +[StructLayout(LayoutKind.Sequential)] +public struct S_StructArray_Seq +{ + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public TestStruct[] arr; +} + +[StructLayout(LayoutKind.Sequential)] +public struct S_BOOLArray_Seq +{ + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public bool[] arr; +} +#endregion + +#region sequential class definition +[StructLayout(LayoutKind.Sequential)] +public class C_INTArray_Seq +{ + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public int[] arr; +} + +[StructLayout(LayoutKind.Sequential)] +public class C_UINTArray_Seq +{ + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public uint[] arr; +} + +[StructLayout(LayoutKind.Sequential)] +public class C_SHORTArray_Seq +{ + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public short[] arr; +} + +[StructLayout(LayoutKind.Sequential)] +public class C_WORDArray_Seq +{ + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public ushort[] arr; +} + +[StructLayout(LayoutKind.Sequential)] +public class C_LONG64Array_Seq +{ + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public long[] arr; +} + +[StructLayout(LayoutKind.Sequential)] +public class C_ULONG64Array_Seq +{ + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public ulong[] arr; +} + +[StructLayout(LayoutKind.Sequential)] +public class C_DOUBLEArray_Seq +{ + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public double[] arr; +} + +[StructLayout(LayoutKind.Sequential)] +public class C_FLOATArray_Seq +{ + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public float[] arr; +} + +[StructLayout(LayoutKind.Sequential)] +public class C_BYTEArray_Seq +{ + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public byte[] arr; +} + +[StructLayout(LayoutKind.Sequential)] +public class C_CHARArray_Seq +{ + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public char[] arr; +} + +[StructLayout(LayoutKind.Sequential)] +public class C_LPSTRArray_Seq +{ + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public string[] arr; +} + +[StructLayout(LayoutKind.Sequential)] +public class C_LPCSTRArray_Seq +{ + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public string[] arr; +} + +[StructLayout(LayoutKind.Sequential)] +public class C_BSTRArray_Seq +{ + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE, ArraySubType = UnmanagedType.BStr)] + public string[] arr; +} + +//struct array in a class +[StructLayout(LayoutKind.Sequential)] +public class C_StructArray_Seq +{ + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public TestStruct[] arr; +} + +[StructLayout(LayoutKind.Sequential)] +public class C_BOOLArray_Seq +{ + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public bool[] arr; +} +#endregion +#endregion + +#region Explicit + +#region explicit stuct definition +[StructLayout(LayoutKind.Explicit)] +public struct S_INTArray_Exp +{ + [FieldOffset(0)] + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public int[] arr; +} + +[StructLayout(LayoutKind.Explicit)] +public struct S_UINTArray_Exp +{ + [FieldOffset(0)] + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public uint[] arr; +} + +[StructLayout(LayoutKind.Explicit)] +public struct S_SHORTArray_Exp +{ + [FieldOffset(0)] + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public short[] arr; +} + +[StructLayout(LayoutKind.Explicit)] +public struct S_WORDArray_Exp +{ + [FieldOffset(0)] + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public ushort[] arr; +} + +[StructLayout(LayoutKind.Explicit)] +public struct S_LONG64Array_Exp +{ + [FieldOffset(0)] + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE, ArraySubType = UnmanagedType.I8)] + public long[] arr; +} + +[StructLayout(LayoutKind.Explicit)] +public struct S_ULONG64Array_Exp +{ + [FieldOffset(0)] + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public ulong[] arr; +} + +[StructLayout(LayoutKind.Explicit)] +public struct S_DOUBLEArray_Exp +{ + [FieldOffset(0)] + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public double[] arr; +} + +[StructLayout(LayoutKind.Explicit)] +public struct S_FLOATArray_Exp +{ + [FieldOffset(0)] + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public float[] arr; +} + +[StructLayout(LayoutKind.Explicit)] +public struct S_BYTEArray_Exp +{ + [FieldOffset(0)] + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public byte[] arr; +} + +[StructLayout(LayoutKind.Explicit)] +public struct S_CHARArray_Exp +{ + [FieldOffset(0)] + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public char[] arr; +} + +[StructLayout(LayoutKind.Explicit)] +public struct S_LPSTRArray_Exp +{ + [FieldOffset(0)] + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public string[] arr; +} + +[StructLayout(LayoutKind.Explicit)] +public struct S_LPCSTRArray_Exp +{ + [FieldOffset(0)] + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public string[] arr; +} + +[StructLayout(LayoutKind.Explicit)] +public struct S_BSTRArray_Exp +{ + [FieldOffset(0)] + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE, ArraySubType = UnmanagedType.BStr)] + public string[] arr; +} + +//struct array in a struct +[StructLayout(LayoutKind.Explicit)] +public struct S_StructArray_Exp +{ + [FieldOffset(0)] + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public TestStruct[] arr; +} + +[StructLayout(LayoutKind.Explicit)] +public struct S_BOOLArray_Exp +{ + [FieldOffset(0)] + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public bool[] arr; +} +#endregion + +#region explicit class definition +[StructLayout(LayoutKind.Explicit)] +public class C_INTArray_Exp +{ + [FieldOffset(0)] + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public int[] arr; +} + +[StructLayout(LayoutKind.Explicit)] +public class C_UINTArray_Exp +{ + [FieldOffset(0)] + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public uint[] arr; +} + +[StructLayout(LayoutKind.Explicit)] +public class C_SHORTArray_Exp +{ + [FieldOffset(0)] + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public short[] arr; +} + +[StructLayout(LayoutKind.Explicit)] +public class C_WORDArray_Exp +{ + [FieldOffset(0)] + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public ushort[] arr; +} + +[StructLayout(LayoutKind.Explicit, Pack = 8)] +public class C_LONG64Array_Exp +{ + [FieldOffset(0)] + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public long[] arr; +} + +[StructLayout(LayoutKind.Explicit)] +public class C_ULONG64Array_Exp +{ + [FieldOffset(0)] + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public ulong[] arr; +} + +[StructLayout(LayoutKind.Explicit)] +public class C_DOUBLEArray_Exp +{ + [FieldOffset(0)] + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public double[] arr; +} + +[StructLayout(LayoutKind.Explicit)] +public class C_FLOATArray_Exp +{ + [FieldOffset(0)] + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public float[] arr; +} + +[StructLayout(LayoutKind.Explicit)] +public class C_BYTEArray_Exp +{ + [FieldOffset(0)] + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public byte[] arr; +} + +[StructLayout(LayoutKind.Explicit)] +public class C_CHARArray_Exp +{ + [FieldOffset(0)] + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public char[] arr; +} + +[StructLayout(LayoutKind.Explicit)] +public class C_LPSTRArray_Exp +{ + [FieldOffset(0)] + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public string[] arr; +} + +[StructLayout(LayoutKind.Explicit)] +public class C_LPCSTRArray_Exp +{ + [FieldOffset(0)] + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public string[] arr; +} + +[StructLayout(LayoutKind.Explicit)] +public class C_BSTRArray_Exp +{ + [FieldOffset(0)] + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE, ArraySubType = UnmanagedType.BStr)] + public string[] arr; +} + +//struct array in a class +[StructLayout(LayoutKind.Explicit)] +public class C_StructArray_Exp +{ + [FieldOffset(0)] + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public TestStruct[] arr; +} + +[StructLayout(LayoutKind.Explicit)] +public class C_BOOLArray_Exp +{ + [FieldOffset(0)] + [MarshalAs(UnmanagedType.LPArray, SizeConst = Test.ARRAY_SIZE)] + public bool[] arr; +} +#endregion + +#endregion \ No newline at end of file diff --git a/tests/src/Interop/PInvoke/Array/MarshalArrayAsField/LPArrayNative/CMakeLists.txt b/tests/src/Interop/PInvoke/Array/MarshalArrayAsField/LPArrayNative/CMakeLists.txt new file mode 100644 index 0000000..f940a21 --- /dev/null +++ b/tests/src/Interop/PInvoke/Array/MarshalArrayAsField/LPArrayNative/CMakeLists.txt @@ -0,0 +1,15 @@ +#VCXPROJ +cmake_minimum_required (VERSION 2.6) +project (MarshalArrayByValArrayNative) +include ("${CLR_INTEROP_TEST_ROOT}/Interop.cmake") +include_directories("../..") +include_directories(${INC_PLATFORM_DIR}) +set(SOURCES + MarshalArrayByValArrayNative.cpp +) + +# add the executable +add_library (MarshalArrayByValArrayNative SHARED ${SOURCES}) +target_link_libraries(MarshalArrayByValArrayNative ${LINK_LIBRARIES_ADDITIONAL}) +# add the install targets +install (TARGETS MarshalArrayByValArrayNative DESTINATION bin) diff --git a/tests/src/Interop/PInvoke/Array/MarshalArrayAsField/LPArrayNative/MarshalArrayByValArrayNative.cpp b/tests/src/Interop/PInvoke/Array/MarshalArrayAsField/LPArrayNative/MarshalArrayByValArrayNative.cpp new file mode 100644 index 0000000..e80896b --- /dev/null +++ b/tests/src/Interop/PInvoke/Array/MarshalArrayAsField/LPArrayNative/MarshalArrayByValArrayNative.cpp @@ -0,0 +1,575 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#include +#include +#include "MarshalArray.h" + +using namespace std; + +/*---------------------------------------------------------------------------- +macro definition +----------------------------------------------------------------------------*/ + +#define INIT_EXPECTED(__type, __size) \ + __type expected[(__size)]; \ + for ( size_t i = 0; i < (__size); ++i) \ + expected[i] = (__type)i + +#define INIT_EXPECTED_STRUCT(__type, __size, __array_type) \ + __type *expected = (__type *)CoreClrAlloc( sizeof(__type) ); \ + for ( size_t i = 0; i < (__size); ++i) \ + expected->arr[i] = (__array_type)i + +#define EQUALS(__actual, __cActual, __expected) Equals((__actual), (__cActual), (__expected), (int)sizeof(__expected) / sizeof(__expected[0])) + +/*---------------------------------------------------------------------------- +struct definition +----------------------------------------------------------------------------*/ + +typedef struct { INT arr[ARRAY_SIZE]; } S_INTArray; +typedef struct { UINT arr[ARRAY_SIZE]; } S_UINTArray; +typedef struct { SHORT arr[ARRAY_SIZE]; } S_SHORTArray; +typedef struct { WORD arr[ARRAY_SIZE]; } S_WORDArray; +typedef struct { LONG64 arr[ARRAY_SIZE]; } S_LONG64Array; + +typedef struct { ULONG64 arr[ARRAY_SIZE]; } S_ULONG64Array; +typedef struct { DOUBLE arr[ARRAY_SIZE]; } S_DOUBLEArray; +typedef struct { FLOAT arr[ARRAY_SIZE]; } S_FLOATArray; +typedef struct { BYTE arr[ARRAY_SIZE]; } S_BYTEArray; +typedef struct { CHAR arr[ARRAY_SIZE]; } S_CHARArray; + +typedef struct { LPSTR arr[ARRAY_SIZE]; } S_LPSTRArray; +typedef struct { LPCSTR arr[ARRAY_SIZE]; } S_LPCSTRArray; +#ifdef _WIN32 +typedef struct { BSTR arr[ARRAY_SIZE]; } S_BSTRArray; +#endif + +//struct array in a struct + +typedef struct { TestStruct arr[ARRAY_SIZE]; } S_StructArray; + +typedef struct { BOOL arr[ARRAY_SIZE]; } S_BOOLArray; + +/*---------------------------------------------------------------------------- +helper function +----------------------------------------------------------------------------*/ + +TestStruct* InitTestStruct() +{ + TestStruct *expected = (TestStruct *)CoreClrAlloc( sizeof(TestStruct) * ARRAY_SIZE ); + + for ( int i = 0; i < ARRAY_SIZE; i++) + { + expected[i].x = i; + expected[i].d = i; + expected[i].l = i; + expected[i].str = ToString(i); + } + + return expected; +} + +template +BOOL Equals(T *pActual, int cActual, T *pExpected, int cExpected) +{ + if ( pActual == NULL && pExpected == NULL ) + return TRUE; + else if ( cActual != cExpected ) + { + printf("WARNING: Test error - %s\n", __FUNCSIG__); + printf("Array Length: expected: %d, actutl: %d\n", cExpected, cActual); + return FALSE; + } + + for ( size_t i = 0; i < ((size_t) cExpected); ++i ) + { + if ( !IsObjectEquals(pActual[i], pExpected[i]) ) + { + printf("WARNING: Test error - %s\n", __FUNCSIG__); + printf("Array Element Not Equal: index: %d", static_cast(i)); + return FALSE; + } + } + + return TRUE; +} + +bool TestStructEquals(TestStruct Actual[], TestStruct Expected[]) +{ + if ( Actual == NULL && Expected == NULL ) + return true; + else if ( Actual == NULL && Expected != NULL ) + return false; + else if ( Actual != NULL && Expected == NULL ) + return false; + + for ( int i = 0; i < ARRAY_SIZE; ++i ) + { + if ( !(IsObjectEquals(Actual[i].x, Expected[i].x) && + IsObjectEquals(Actual[i].d, Expected[i].d) && + IsObjectEquals(Actual[i].l, Expected[i].l) && + IsObjectEquals(Actual[i].str, Expected[i].str) )) + { + printf("WARNING: Test error - %s\n", __FUNCSIG__); + return false; + } + } + + return true; +} + +/*---------------------------------------------------------------------------- + +Function + +----------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------- +marshal sequential strut +----------------------------------------------------------------------------*/ +extern "C" DLL_EXPORT BOOL __cdecl TakeIntArraySeqStructByVal( S_INTArray s, int size ) +{ + CHECK_PARAM_NOT_EMPTY( s.arr ); + INIT_EXPECTED( INT, ARRAY_SIZE ); + return Equals( s.arr, size, expected, ARRAY_SIZE ); +} + +extern "C" DLL_EXPORT BOOL __cdecl TakeUIntArraySeqStructByVal( S_UINTArray s, int size ) +{ + CHECK_PARAM_NOT_EMPTY( s.arr ); + INIT_EXPECTED( UINT, ARRAY_SIZE ); + return Equals( s.arr, size, expected, ARRAY_SIZE ); +} + +extern "C" DLL_EXPORT BOOL __cdecl TakeShortArraySeqStructByVal( S_SHORTArray s, int size ) +{ + CHECK_PARAM_NOT_EMPTY( s.arr ); + INIT_EXPECTED( SHORT, ARRAY_SIZE ); + return Equals( s.arr, size, expected, ARRAY_SIZE ); +} + +extern "C" DLL_EXPORT BOOL __cdecl TakeWordArraySeqStructByVal( S_WORDArray s, int size ) +{ + CHECK_PARAM_NOT_EMPTY( s.arr ); + INIT_EXPECTED( WORD, ARRAY_SIZE ); + return Equals( s.arr, size, expected, ARRAY_SIZE ); +} + +extern "C" DLL_EXPORT BOOL __cdecl TakeLong64ArraySeqStructByVal( S_LONG64Array s, int size ) +{ + CHECK_PARAM_NOT_EMPTY( s.arr ); + INIT_EXPECTED( LONG64, ARRAY_SIZE ); + return Equals( s.arr, size, expected, ARRAY_SIZE ); +} + +extern "C" DLL_EXPORT BOOL __cdecl TakeULong64ArraySeqStructByVal( S_ULONG64Array s, int size ) +{ + CHECK_PARAM_NOT_EMPTY( s.arr ); + INIT_EXPECTED( ULONG64, ARRAY_SIZE ); + return Equals( s.arr, size, expected, ARRAY_SIZE ); +} + +extern "C" DLL_EXPORT BOOL __cdecl TakeDoubleArraySeqStructByVal( S_DOUBLEArray s, int size ) +{ + CHECK_PARAM_NOT_EMPTY( s.arr ); + INIT_EXPECTED( DOUBLE, ARRAY_SIZE ); + return Equals( s.arr, size, expected, ARRAY_SIZE ); +} + +extern "C" DLL_EXPORT BOOL __cdecl TakeFloatArraySeqStructByVal( S_FLOATArray s, int size ) +{ + CHECK_PARAM_NOT_EMPTY( s.arr ); + INIT_EXPECTED( FLOAT, ARRAY_SIZE ); + return Equals( s.arr, size, expected, ARRAY_SIZE ); +} + +extern "C" DLL_EXPORT BOOL __cdecl TakeByteArraySeqStructByVal( S_BYTEArray s, int size ) +{ + CHECK_PARAM_NOT_EMPTY( s.arr ); + INIT_EXPECTED( BYTE, ARRAY_SIZE ); + return Equals( s.arr, size, expected, ARRAY_SIZE ); +} + +extern "C" DLL_EXPORT BOOL __cdecl TakeCharArraySeqStructByVal( S_CHARArray s, int size ) +{ + CHECK_PARAM_NOT_EMPTY( s.arr ); + INIT_EXPECTED( CHAR, ARRAY_SIZE ); + return Equals( s.arr, size, expected, ARRAY_SIZE ); +} + +extern "C" DLL_EXPORT BOOL __cdecl TakeLPSTRArraySeqStructByVal( S_LPSTRArray s, int size ) +{ + CHECK_PARAM_NOT_EMPTY( s.arr ); + + LPSTR expected[ARRAY_SIZE]; + for ( int i = 0; i < ARRAY_SIZE; ++i ) + expected[i] = ToString(i); + + return Equals( s.arr, size, expected, ARRAY_SIZE ); +} + +extern "C" DLL_EXPORT BOOL __cdecl TakeLPCSTRArraySeqStructByVal( S_LPCSTRArray s, int size ) +{ + CHECK_PARAM_NOT_EMPTY( s.arr ); + + LPSTR expected[ARRAY_SIZE]; + for ( int i = 0; i < ARRAY_SIZE; ++i ) + expected[i] = ToString(i); + + return Equals( s.arr, size, (LPCSTR *)expected, ARRAY_SIZE ); +} + +#ifdef _WIN32 +extern "C" DLL_EXPORT BOOL __cdecl TakeBSTRArraySeqStructByVal( S_BSTRArray s, int size ) +{ + CHECK_PARAM_NOT_EMPTY( s.arr ); + + BSTR expected[ARRAY_SIZE]; + for ( int i = 0; i < ARRAY_SIZE; ++i ) + expected[i] = ToBSTR(i); + + return Equals( s.arr, size, expected, ARRAY_SIZE ); +} +#endif + +extern "C" DLL_EXPORT BOOL __cdecl TakeStructArraySeqStructByVal( S_StructArray s, int size ) +{ + CHECK_PARAM_NOT_EMPTY( s.arr ); + + TestStruct *expected = InitTestStruct(); + return TestStructEquals( s.arr,expected ); +} + +/*---------------------------------------------------------------------------- +marshal sequential class +----------------------------------------------------------------------------*/ +extern "C" DLL_EXPORT BOOL __cdecl TakeIntArraySeqClassByVal( S_INTArray *s, int size ) +{ + return TakeIntArraySeqStructByVal( *s, size ); +} + +extern "C" DLL_EXPORT BOOL __cdecl TakeUIntArraySeqClassByVal( S_UINTArray *s, int size ) +{ + return TakeUIntArraySeqStructByVal( *s, size ); +} + +extern "C" DLL_EXPORT BOOL __cdecl TakeShortArraySeqClassByVal( S_SHORTArray *s, int size ) +{ + return TakeShortArraySeqStructByVal( *s, size ); +} + +extern "C" DLL_EXPORT BOOL __cdecl TakeWordArraySeqClassByVal( S_WORDArray *s, int size ) +{ + return TakeWordArraySeqStructByVal( *s, size ); +} + +extern "C" DLL_EXPORT BOOL __cdecl TakeLong64ArraySeqClassByVal( S_LONG64Array *s, int size ) +{ + return TakeLong64ArraySeqStructByVal( *s, size ); +} + +extern "C" DLL_EXPORT BOOL __cdecl TakeULong64ArraySeqClassByVal( S_ULONG64Array *s, int size ) +{ + return TakeULong64ArraySeqStructByVal( *s, size ); +} + +extern "C" DLL_EXPORT BOOL __cdecl TakeDoubleArraySeqClassByVal( S_DOUBLEArray *s, int size ) +{ + return TakeDoubleArraySeqStructByVal( *s, size ); +} + +extern "C" DLL_EXPORT BOOL __cdecl TakeFloatArraySeqClassByVal( S_FLOATArray *s, int size ) +{ + return TakeFloatArraySeqStructByVal( *s, size ); +} + +extern "C" DLL_EXPORT BOOL __cdecl TakeByteArraySeqClassByVal( S_BYTEArray *s, int size ) +{ + return TakeByteArraySeqStructByVal( *s, size ); +} + +extern "C" DLL_EXPORT BOOL __cdecl TakeCharArraySeqClassByVal( S_CHARArray *s, int size ) +{ + return TakeCharArraySeqStructByVal( *s, size ); +} + +extern "C" DLL_EXPORT BOOL __cdecl TakeLPSTRArraySeqClassByVal( S_LPSTRArray *s, int size ) +{ + return TakeLPSTRArraySeqStructByVal( *s, size ); +} + +extern "C" DLL_EXPORT BOOL __cdecl TakeLPCSTRArraySeqClassByVal( S_LPCSTRArray *s, int size ) +{ + return TakeLPCSTRArraySeqStructByVal( *s, size ); +} + +#ifdef _WIN32 +extern "C" DLL_EXPORT BOOL __cdecl TakeBSTRArraySeqClassByVal( S_BSTRArray *s, int size ) +{ + return TakeBSTRArraySeqStructByVal( *s, size ); +} +#endif + +extern "C" DLL_EXPORT BOOL __cdecl TakeStructArraySeqClassByVal( S_StructArray *s, int size ) +{ + return TakeStructArraySeqStructByVal( *s, size ); +} + +/*---------------------------------------------------------------------------- +marshal explicit struct +----------------------------------------------------------------------------*/ +extern "C" DLL_EXPORT BOOL __cdecl TakeIntArrayExpStructByVal( S_INTArray s, int size ) +{ + return TakeIntArraySeqStructByVal( s, size ); +} + +extern "C" DLL_EXPORT BOOL __cdecl TakeUIntArrayExpStructByVal( S_UINTArray s, int size ) +{ + return TakeUIntArraySeqStructByVal( s, size ); +} + +extern "C" DLL_EXPORT BOOL __cdecl TakeShortArrayExpStructByVal( S_SHORTArray s, int size ) +{ + return TakeShortArraySeqStructByVal( s, size ); +} + +extern "C" DLL_EXPORT BOOL __cdecl TakeWordArrayExpStructByVal( S_WORDArray s, int size ) +{ + return TakeWordArraySeqStructByVal( s, size ); +} + +extern "C" DLL_EXPORT BOOL __cdecl TakeLong64ArrayExpStructByVal( S_LONG64Array s, int size ) +{ + return TakeLong64ArraySeqStructByVal( s, size ); +} + +extern "C" DLL_EXPORT BOOL __cdecl TakeULong64ArrayExpStructByVal( S_ULONG64Array s, int size ) +{ + return TakeULong64ArraySeqStructByVal( s, size ); +} + +extern "C" DLL_EXPORT BOOL __cdecl TakeDoubleArrayExpStructByVal( S_DOUBLEArray s, int size ) +{ + return TakeDoubleArraySeqStructByVal( s, size ); +} + +extern "C" DLL_EXPORT BOOL __cdecl TakeFloatArrayExpStructByVal( S_FLOATArray s, int size ) +{ + return TakeFloatArraySeqStructByVal( s, size ); +} + +extern "C" DLL_EXPORT BOOL __cdecl TakeByteArrayExpStructByVal( S_BYTEArray s, int size ) +{ + return TakeByteArraySeqStructByVal( s, size ); +} + +extern "C" DLL_EXPORT BOOL __cdecl TakeCharArrayExpStructByVal( S_CHARArray s, int size ) +{ + return TakeCharArraySeqStructByVal( s, size ); +} + +extern "C" DLL_EXPORT BOOL __cdecl TakeLPSTRArrayExpStructByVal( S_LPSTRArray s, int size ) +{ + return TakeLPSTRArraySeqStructByVal( s, size ); +} + +extern "C" DLL_EXPORT BOOL __cdecl TakeLPCSTRArrayExpStructByVal( S_LPCSTRArray s, int size ) +{ + return TakeLPCSTRArraySeqStructByVal( s, size ); +} + +#ifdef _WIN32 +extern "C" DLL_EXPORT BOOL __cdecl TakeBSTRArrayExpStructByVal( S_BSTRArray s, int size ) +{ + return TakeBSTRArraySeqStructByVal( s, size ); +} +#endif + +extern "C" DLL_EXPORT BOOL __cdecl TakeStructArrayExpStructByVal( S_StructArray s, int size ) +{ + return TakeStructArraySeqStructByVal( s, size ); +} + +/*---------------------------------------------------------------------------- +marshal explicit class +----------------------------------------------------------------------------*/ +extern "C" DLL_EXPORT BOOL __cdecl TakeIntArrayExpClassByVal( S_INTArray *s, int size ) +{ + return TakeIntArraySeqStructByVal( *s, size ); +} + +extern "C" DLL_EXPORT BOOL __cdecl TakeUIntArrayExpClassByVal( S_UINTArray *s, int size ) +{ + return TakeUIntArraySeqStructByVal( *s, size ); +} + +extern "C" DLL_EXPORT BOOL __cdecl TakeShortArrayExpClassByVal( S_SHORTArray *s, int size ) +{ + return TakeShortArraySeqStructByVal( *s, size ); +} + +extern "C" DLL_EXPORT BOOL __cdecl TakeWordArrayExpClassByVal( S_WORDArray *s, int size ) +{ + return TakeWordArraySeqStructByVal( *s, size ); +} + +extern "C" DLL_EXPORT BOOL __cdecl TakeLong64ArrayExpClassByVal( S_LONG64Array *s, int size ) +{ + return TakeLong64ArraySeqStructByVal( *s, size ); +} + +extern "C" DLL_EXPORT BOOL __cdecl TakeULong64ArrayExpClassByVal( S_ULONG64Array *s, int size ) +{ + return TakeULong64ArraySeqStructByVal( *s, size ); +} + +extern "C" DLL_EXPORT BOOL __cdecl TakeDoubleArrayExpClassByVal( S_DOUBLEArray *s, int size ) +{ + return TakeDoubleArraySeqStructByVal( *s, size ); +} + +extern "C" DLL_EXPORT BOOL __cdecl TakeFloatArrayExpClassByVal( S_FLOATArray *s, int size ) +{ + return TakeFloatArraySeqStructByVal( *s, size ); +} + +extern "C" DLL_EXPORT BOOL __cdecl TakeByteArrayExpClassByVal( S_BYTEArray *s, int size ) +{ + return TakeByteArraySeqStructByVal( *s, size ); +} + +extern "C" DLL_EXPORT BOOL __cdecl TakeCharArrayExpClassByVal( S_CHARArray *s, int size ) +{ + return TakeCharArraySeqStructByVal( *s, size ); +} + +extern "C" DLL_EXPORT BOOL __cdecl TakeLPSTRArrayExpClassByVal( S_LPSTRArray *s, int size ) +{ + return TakeLPSTRArraySeqStructByVal( *s, size ); +} + +extern "C" DLL_EXPORT BOOL __cdecl TakeLPCSTRArrayExpClassByVal( S_LPCSTRArray *s, int size ) +{ + return TakeLPCSTRArraySeqStructByVal( *s, size ); +} + +#ifdef _WIN32 +extern "C" DLL_EXPORT BOOL __cdecl TakeBSTRArrayExpClassByVal( S_BSTRArray *s, int size ) +{ + return TakeBSTRArraySeqStructByVal( *s, size ); +} +#endif + +extern "C" DLL_EXPORT BOOL __cdecl TakeStructArrayExpClassByVal( S_StructArray *s, int size ) +{ + return TakeStructArraySeqStructByVal( *s, size ); +} + +/*---------------------------------------------------------------------------- +return a struct including a C array +----------------------------------------------------------------------------*/ +extern "C" DLL_EXPORT S_INTArray* __cdecl S_INTArray_Ret() +{ + INIT_EXPECTED_STRUCT( S_INTArray, ARRAY_SIZE, INT ); + + return expected; +} + +extern "C" DLL_EXPORT S_UINTArray* __cdecl S_UINTArray_Ret() +{ + INIT_EXPECTED_STRUCT( S_UINTArray, ARRAY_SIZE, UINT ); + + return expected; +} + +extern "C" DLL_EXPORT S_SHORTArray* __cdecl S_SHORTArray_Ret() +{ + INIT_EXPECTED_STRUCT( S_SHORTArray, ARRAY_SIZE, SHORT ); + + return expected; +} + +extern "C" DLL_EXPORT S_WORDArray* __cdecl S_WORDArray_Ret() +{ + INIT_EXPECTED_STRUCT( S_WORDArray, ARRAY_SIZE, WORD ); + + return expected; +} + +extern "C" DLL_EXPORT S_LONG64Array* __cdecl S_LONG64Array_Ret() +{ + INIT_EXPECTED_STRUCT( S_LONG64Array, ARRAY_SIZE, LONG64 ); + + return expected; +} + +extern "C" DLL_EXPORT S_ULONG64Array* __cdecl S_ULONG64Array_Ret() +{ + INIT_EXPECTED_STRUCT( S_ULONG64Array, ARRAY_SIZE, ULONG64 ); + + return expected; +} + +extern "C" DLL_EXPORT S_DOUBLEArray* __cdecl S_DOUBLEArray_Ret() +{ + INIT_EXPECTED_STRUCT( S_DOUBLEArray, ARRAY_SIZE, DOUBLE ); + + return expected; +} + +extern "C" DLL_EXPORT S_FLOATArray* __cdecl S_FLOATArray_Ret() +{ + INIT_EXPECTED_STRUCT( S_FLOATArray, ARRAY_SIZE, FLOAT ); + + return expected; +} + +extern "C" DLL_EXPORT S_BYTEArray* __cdecl S_BYTEArray_Ret() +{ + INIT_EXPECTED_STRUCT( S_BYTEArray, ARRAY_SIZE, BYTE ); + + return expected; +} + +extern "C" DLL_EXPORT S_CHARArray* __cdecl S_CHARArray_Ret() +{ + INIT_EXPECTED_STRUCT( S_CHARArray, ARRAY_SIZE, CHAR ); + + return expected; +} + +extern "C" DLL_EXPORT S_LPSTRArray* __cdecl S_LPSTRArray_Ret() +{ + S_LPSTRArray *expected = (S_LPSTRArray *)CoreClrAlloc( sizeof(S_LPSTRArray) ); + for ( int i = 0; i < ARRAY_SIZE; ++i ) + expected->arr[i] = ToString(i); + + return expected; +} + +#ifdef _WIN32 +extern "C" DLL_EXPORT S_BSTRArray* __cdecl S_BSTRArray_Ret() +{ + S_BSTRArray *expected = (S_BSTRArray *)CoreClrAlloc( sizeof(S_BSTRArray) ); + for ( int i = 0; i < ARRAY_SIZE; ++i ) + expected->arr[i] = ToBSTR(i); + + return expected; +} +#endif + +extern "C" DLL_EXPORT S_StructArray* __cdecl S_StructArray_Ret() +{ + S_StructArray *expected = (S_StructArray *)CoreClrAlloc( sizeof(S_StructArray) ); + for ( int i = 0; i < ARRAY_SIZE; ++i ) + { + expected->arr[i].x = i; + expected->arr[i].d = i; + expected->arr[i].l = i; + expected->arr[i].str = ToString(i); + } + + return expected; +} diff --git a/tests/src/Interop/PInvoke/Array/MarshalArrayAsParam/AsDefault/AsDefaultTest.cs b/tests/src/Interop/PInvoke/Array/MarshalArrayAsParam/AsDefault/AsDefaultTest.cs new file mode 100644 index 0000000..1297c87 --- /dev/null +++ b/tests/src/Interop/PInvoke/Array/MarshalArrayAsParam/AsDefault/AsDefaultTest.cs @@ -0,0 +1,640 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; +using TestLibrary; + +public class ArrayMarshal +{ + public struct TestStruct + { + public int x; + public double d; + public long l; + public string str; + } + + #region No attributes applied + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Int(int[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Uint(uint[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Short(short[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Word(ushort[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Long64(long[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_ULong64(ulong[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Double(double[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Float(float[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Byte(byte[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Char(char[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_LPCSTR(string[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_LPSTR(string[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Struct(TestStruct[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Bool(bool[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Object(object[] actual, int cActual); + #endregion + + #region InAttribute attribute applied + + [DllImport("MarshalArrayLPArrayNative", EntryPoint = "CStyle_Array_Int")] + private static extern bool CStyle_Array_Int_In([In]int[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative", EntryPoint = "CStyle_Array_Uint")] + private static extern bool CStyle_Array_Uint_In([In]uint[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative", EntryPoint = "CStyle_Array_Short")] + private static extern bool CStyle_Array_Short_In([In]short[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative", EntryPoint = "CStyle_Array_Word")] + private static extern bool CStyle_Array_Word_In([In]ushort[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative", EntryPoint = "CStyle_Array_Long64")] + private static extern bool CStyle_Array_Long64_In([In]long[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative", EntryPoint = "CStyle_Array_ULong64")] + private static extern bool CStyle_Array_ULong64_In([In]ulong[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative", EntryPoint = "CStyle_Array_Double")] + private static extern bool CStyle_Array_Double_In([In]double[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative", EntryPoint = "CStyle_Array_Float")] + private static extern bool CStyle_Array_Float_In([In]float[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative", EntryPoint = "CStyle_Array_Byte")] + private static extern bool CStyle_Array_Byte_In([In]byte[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative", EntryPoint = "CStyle_Array_Char")] + private static extern bool CStyle_Array_Char_In([In]char[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative", EntryPoint = "CStyle_Array_LPCSTR")] + private static extern bool CStyle_Array_LPCSTR_In([In]string[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative", EntryPoint = "CStyle_Array_LPSTR")] + private static extern bool CStyle_Array_LPSTR_In([In]string[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative", EntryPoint = "CStyle_Array_Struct")] + private static extern bool CStyle_Array_Struct_In([In]TestStruct[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative", EntryPoint = "CStyle_Array_Bool")] + private static extern bool CStyle_Array_Bool_In([In]bool[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative", EntryPoint = "CStyle_Array_Object")] + private static extern bool CStyle_Array_Object_In([In]object[] actual, int cActual); + #endregion + + #region InAttribute and OutAttribute attributes applied + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Int_InOut( + [In, Out] int[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Int_InOut_Null( + [In, Out] int[] actual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Int_InOut_ZeroLength( + [In, Out] int[] actual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Object_InOut( + [In, Out] object[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Uint_InOut( + [In, Out] uint[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Short_InOut( + [In, Out] short[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Word_InOut( + [In, Out] ushort[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Long64_InOut( + [In, Out] long[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_ULong64_InOut( + [In, Out] ulong[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Double_InOut( + [In, Out] double[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Float_InOut( + [In, Out] float[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Byte_InOut( + [In, Out] byte[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Char_InOut( + [In, Out] char[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_LPSTR_InOut( + [In, Out] string[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Struct_InOut( + [In, Out] TestStruct[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Bool_InOut( + [In, Out] bool[] actual, int cActual); + #endregion + + #region OutAttribute attributes applied + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Int_Out( + [Out] int[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Int_Out_Null( + [Out] int[] actual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Int_Out_ZeroLength( + [Out] int[] actual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Object_Out( + [Out] object[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Uint_Out( + [Out] uint[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Short_Out( + [Out] short[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Word_Out( + [Out] ushort[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Long64_Out( + [Out] long[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_ULong64_Out( + [Out] ulong[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Double_Out( + [Out] double[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Float_Out( + [Out] float[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Byte_Out( + [Out] byte[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Char_Out( + [Out] char[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_LPSTR_Out( + [Out] string[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Struct_Out( + [Out] TestStruct[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Bool_Out( + [Out] bool[] actual, int cActual); + #endregion + + #region Marshal ByVal + + private const int ARRAY_SIZE = 100; + + private static T[] InitArray(int size) + { + T[] array = new T[size]; + + for (int i = 0; i < array.Length; ++i) + array[i] = (T)Convert.ChangeType(i, typeof(T)); + + return array; + } + + private static bool[] InitBoolArray(int size) + { + bool[] array = new bool[size]; + + for (int i = 0; i < array.Length; ++i) + { + if (i % 2 == 0) + array[i] = true; + else + array[i] = false; + } + + return array; + } + + private static TestStruct[] InitStructArray(int size) + { + TestStruct[] array = new TestStruct[size]; + + for (int i = 0; i < array.Length; ++i) + { + array[i].x = i; + array[i].d = i; + array[i].l = i; + array[i].str = i.ToString(); + } + + return array; + } + + private static void TestMarshalByVal_NoAttributes() + { + Console.WriteLine("ByVal marshaling CLR array as c-style-array no attributes"); + + Assert.IsTrue(CStyle_Array_Int(InitArray(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Int"); + Assert.IsTrue(CStyle_Array_Uint(InitArray(ARRAY_SIZE), ARRAY_SIZE),"CStyle_Array_Uint") ; + Assert.IsTrue(CStyle_Array_Short(InitArray(ARRAY_SIZE), ARRAY_SIZE),"CStyle_Array_Short"); + Assert.IsTrue(CStyle_Array_Word(InitArray(ARRAY_SIZE), ARRAY_SIZE),"CStyle_Array_Word"); + Assert.IsTrue(CStyle_Array_Long64(InitArray(ARRAY_SIZE), ARRAY_SIZE),"CStyle_Array_Long64"); + Assert.IsTrue(CStyle_Array_ULong64(InitArray(ARRAY_SIZE), ARRAY_SIZE),"CStyle_Array_ULong64"); + Assert.IsTrue(CStyle_Array_Double(InitArray(ARRAY_SIZE), ARRAY_SIZE),"CStyle_Array_Double"); + Assert.IsTrue(CStyle_Array_Float(InitArray(ARRAY_SIZE), ARRAY_SIZE),"CStyle_Array_Float"); + Assert.IsTrue(CStyle_Array_Byte(InitArray(ARRAY_SIZE), ARRAY_SIZE),"CStyle_Array_Byte"); + Assert.IsTrue(CStyle_Array_Char(InitArray(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Char"); + + string[] strArr = InitArray(ARRAY_SIZE); + // Test nesting null value scenario + strArr[strArr.Length / 2] = null; + Assert.IsTrue(CStyle_Array_LPCSTR(strArr, ARRAY_SIZE), "CStyle_Array_LPCSTR"); + Assert.IsTrue(CStyle_Array_LPSTR(strArr, ARRAY_SIZE), "CStyle_Array_LPSTR"); + Assert.IsTrue(CStyle_Array_Struct(InitStructArray(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Struct"); + + Assert.IsTrue(CStyle_Array_Bool(InitBoolArray(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Bool"); + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + object[] oArr = InitArray(ARRAY_SIZE); + // Test nesting null value scenario + oArr[oArr.Length / 2] = null; + Assert.IsTrue(CStyle_Array_Object(oArr, ARRAY_SIZE), "CStyle_Array_Object"); + } + } + + private static void TestMarshalByVal_In() + { + Console.WriteLine("ByVal marshaling CLR array as c-style-array with InAttribute applied"); + + Assert.IsTrue(CStyle_Array_Int_In(InitArray(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Int_In"); + Assert.IsTrue(CStyle_Array_Uint_In(InitArray(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Uint_In"); + Assert.IsTrue(CStyle_Array_Short_In(InitArray(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Short_In"); + Assert.IsTrue(CStyle_Array_Word_In(InitArray(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Word_In"); + Assert.IsTrue(CStyle_Array_Long64_In(InitArray(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Long64_In"); + Assert.IsTrue(CStyle_Array_ULong64_In(InitArray(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_ULong64_In"); + Assert.IsTrue(CStyle_Array_Double_In(InitArray(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Double_In"); + Assert.IsTrue(CStyle_Array_Float_In(InitArray(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Float_In"); + Assert.IsTrue(CStyle_Array_Byte_In(InitArray(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Byte_In"); + Assert.IsTrue(CStyle_Array_Char_In(InitArray(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Char_In"); + + string[] strArr = InitArray(ARRAY_SIZE); + // Test nesting null value scenario + strArr[strArr.Length / 2] = null; + + Assert.IsTrue(CStyle_Array_LPCSTR_In(strArr, ARRAY_SIZE), "CStyle_Array_LPCSTR_In"); + Assert.IsTrue(CStyle_Array_LPSTR_In(strArr, ARRAY_SIZE), "CStyle_Array_LPSTR_In"); + Assert.IsTrue(CStyle_Array_Struct_In(InitStructArray(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Struct_In"); + Assert.IsTrue(CStyle_Array_Bool_In(InitBoolArray(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Bool_In"); + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + object[] oArr = InitArray(ARRAY_SIZE); + // Test nesting null value scenario + oArr[oArr.Length / 2] = null; + Assert.IsTrue(CStyle_Array_Object_In(oArr, ARRAY_SIZE), "CStyle_Array_Object_In"); + } + } + + #endregion + + #region Marshal InOut ByVal + + private static void TestMarshalInOut_ByVal() + { + Console.WriteLine("By value marshaling CLR array as c-style-array with InAttribute and OutAttribute applied"); + Console.WriteLine("CStyle_Array_Int_InOut"); + int[] iArr = InitArray(ARRAY_SIZE); + Assert.IsTrue(CStyle_Array_Int_InOut(iArr, ARRAY_SIZE), "CStyle_Array_Int_InOut"); + Assert.IsTrue(Equals(iArr, GetExpectedOutArray(ARRAY_SIZE)), "CStyle_Array_Int_InOut:Equals"); + + Console.WriteLine("CStyle_Array_Int_InOut_Null"); + int[] iArrNull = null; + Assert.IsTrue(CStyle_Array_Int_InOut_Null(iArrNull), "CStyle_Array_Int_InOut_Null"); + Assert.IsNull(iArrNull, "CStyle_Array_Int_InOut_Null:Equals"); + + Console.WriteLine("CStyle_Array_Int_InOut_ZeroLength"); + int[] iArrLength0 = InitArray(0); + Assert.IsTrue(CStyle_Array_Int_InOut_ZeroLength(iArrLength0), "CStyle_Array_Int_InOut_ZeroLength"); + Assert.AreEqual(0, iArrLength0.Length, "CStyle_Array_Int_InOut_ZeroLength:Length"); + + Console.WriteLine("CStyle_Array_Uint_InOut"); + uint[] uiArr = InitArray(ARRAY_SIZE); + Assert.IsTrue(CStyle_Array_Uint_InOut(uiArr, ARRAY_SIZE), "CStyle_Array_Uint_InOut"); + Assert.IsTrue(Equals(uiArr, GetExpectedOutArray(ARRAY_SIZE)), "CStyle_Array_Uint_InOut:Equals"); + + Console.WriteLine("CStyle_Array_Short_InOut"); + short[] sArr = InitArray(ARRAY_SIZE); + Assert.IsTrue(CStyle_Array_Short_InOut(sArr, ARRAY_SIZE), "CStyle_Array_Short_InOut"); + Assert.IsTrue(Equals(sArr, GetExpectedOutArray(ARRAY_SIZE)), "CStyle_Array_Short_InOut:Equals"); + + Console.WriteLine("CStyle_Array_Word_InOut"); + ushort[] usArr = InitArray(ARRAY_SIZE); + Assert.IsTrue(CStyle_Array_Word_InOut(usArr, ARRAY_SIZE), "CStyle_Array_Word_InOut"); + Assert.IsTrue(Equals(usArr, GetExpectedOutArray(ARRAY_SIZE)), "CStyle_Array_Word_InOut:Equals"); + + Console.WriteLine("CStyle_Array_Long64_InOut"); + long[] lArr = InitArray(ARRAY_SIZE); + Assert.IsTrue(CStyle_Array_Long64_InOut(lArr, ARRAY_SIZE), "CStyle_Array_Long64_InOut"); + Assert.IsTrue(Equals(lArr, GetExpectedOutArray(ARRAY_SIZE)), "CStyle_Array_Long64_InOut:Equals"); + + Console.WriteLine("CStyle_Array_ULong64_InOut"); + ulong[] ulArr = InitArray(ARRAY_SIZE); + Assert.IsTrue(CStyle_Array_ULong64_InOut(ulArr, ARRAY_SIZE), "CStyle_Array_ULong64_InOut"); + Assert.IsTrue(Equals(ulArr, GetExpectedOutArray(ARRAY_SIZE)), "CStyle_Array_ULong64_InOut:Equals"); + + Console.WriteLine("CStyle_Array_Double_InOut"); + double[] dArr = InitArray(ARRAY_SIZE); + Assert.IsTrue(CStyle_Array_Double_InOut(dArr, ARRAY_SIZE), "CStyle_Array_Double_InOut"); + Assert.IsTrue(Equals(dArr, GetExpectedOutArray(ARRAY_SIZE)), "CStyle_Array_Double_InOut:Equals"); + + Console.WriteLine("CStyle_Array_Float_InOut"); + float[] fArr = InitArray(ARRAY_SIZE); + Assert.IsTrue(CStyle_Array_Float_InOut(fArr, ARRAY_SIZE), "CStyle_Array_Float_InOut"); + Assert.IsTrue(Equals(fArr, GetExpectedOutArray(ARRAY_SIZE)), "CStyle_Array_Float_InOut:Equals"); + + Console.WriteLine("CStyle_Array_Byte_InOut"); + byte[] bArr = InitArray(ARRAY_SIZE); + Assert.IsTrue(CStyle_Array_Byte_InOut(bArr, ARRAY_SIZE), "CStyle_Array_Byte_InOut"); + Assert.IsTrue(Equals(bArr, GetExpectedOutArray(ARRAY_SIZE)), "CStyle_Array_Byte_InOut:Equals"); + + Console.WriteLine("CStyle_Array_Char_InOut"); + char[] cArr = InitArray(ARRAY_SIZE); + Assert.IsTrue(CStyle_Array_Char_InOut(cArr, ARRAY_SIZE), "CStyle_Array_Char_InOut"); + Assert.IsTrue(Equals(cArr, GetExpectedOutArray(ARRAY_SIZE)), "CStyle_Array_Char_InOut:Equals"); + + Console.WriteLine("CStyle_Array_LPSTR_InOut"); + string[] strArr = InitArray(ARRAY_SIZE); + strArr[strArr.Length / 2] = null; + Assert.IsTrue(CStyle_Array_LPSTR_InOut(strArr, ARRAY_SIZE), "CStyle_Array_LPSTR_InOut"); + string[] expectedArr = GetExpectedOutArray(ARRAY_SIZE); + // Test nesting null value scenario + expectedArr[expectedArr.Length / 2 - 1] = null; + Assert.IsTrue(Equals(strArr, expectedArr), "CStyle_Array_LPSTR_InOut:Equals"); + + Console.WriteLine("CStyle_Array_Struct_InOut"); + TestStruct[] tsArr = InitStructArray(ARRAY_SIZE); + Assert.IsTrue(CStyle_Array_Struct_InOut(tsArr, ARRAY_SIZE), "CStyle_Array_Struct_InOut"); + Assert.IsTrue(Equals(tsArr, GetExpectedOutStructArray(ARRAY_SIZE)), "CStyle_Array_Struct_InOut:Equals"); + + Console.WriteLine("CStyle_Array_Bool_InOut"); + bool[] boolArr = InitBoolArray(ARRAY_SIZE); + Assert.IsTrue(CStyle_Array_Bool_InOut(boolArr, ARRAY_SIZE), "CStyle_Array_Bool_InOut"); + Assert.IsTrue(Equals(boolArr, GetExpectedOutBoolArray(ARRAY_SIZE)), "CStyle_Array_Bool_InOut:Equals"); + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + Console.WriteLine("CStyle_Array_Object_InOut"); + object[] oArr = InitArray(ARRAY_SIZE); + oArr[oArr.Length / 2] = null; + Assert.IsTrue(CStyle_Array_Object_InOut(oArr, ARRAY_SIZE), "CStyle_Array_Object_InOut"); + + object[] expectedOArr = GetExpectedOutArray(ARRAY_SIZE); + // Test nesting null value scenario + expectedOArr[expectedOArr.Length / 2 - 1] = null; + Assert.IsTrue(Equals(oArr, expectedOArr), "CStyle_Array_Object_InOut:Equals"); + } + } + + private static bool Equals(T[] arr1, T[] arr2) + { + if (arr1 == null && arr2 == null) + return true; + else if (arr1 == null && arr2 != null) + return false; + else if (arr1 != null && arr2 == null) + return false; + else if (arr1.Length != arr2.Length) + return false; + + for (int i = 0; i < arr2.Length; ++i) + { + if (!Object.Equals(arr1[i], arr2[i])) + { + Console.WriteLine("Array marshaling error: Index: {0} : Actual:{1}, Expected:{2},", i, arr1[i], arr2[i]); + return false; + } + } + + return true; + } + + private static T[] GetExpectedOutArray(int size) + { + T[] array = new T[size]; + + for (int i = array.Length - 1; i >= 0; --i) + array[i] = (T)Convert.ChangeType(array.Length - 1 - i, typeof(T)); + + return array; + } + + private static bool[] GetExpectedOutBoolArray(int size) + { + bool[] array = new bool[size]; + + for (int i = 0; i < array.Length; ++i) + { + if (i % 2 != 0) + array[i] = true; + else + array[i] = false; + } + + return array; + } + + private static TestStruct[] GetExpectedOutStructArray(int size) + { + TestStruct[] array = new TestStruct[size]; + + for (int i = array.Length - 1; i >= 0; --i) + { + int v = array.Length - 1 - i; + array[i].x = v; + array[i].d = v; + array[i].l = v; + array[i].str = v.ToString(); + } + + return array; + } + + #endregion + + #region Marshal Out ByVal + + private static void TestMarshalOut_ByVal() + { + Console.WriteLine("By value marshaling CLR array as c-style-array with OutAttribute applied"); + + Console.WriteLine("CStyle_Array_Int_Out"); + int[] iArr = new int[ARRAY_SIZE]; + Assert.IsTrue(CStyle_Array_Int_Out(iArr, ARRAY_SIZE), "CStyle_Array_Int_Out"); + Assert.IsTrue(Equals(iArr, GetExpectedOutArray(ARRAY_SIZE)), "CStyle_Array_Int_Out:Equals"); + + Console.WriteLine("CStyle_Array_Int_Out_Null"); + int[] iArrNull = null; + Assert.IsTrue(CStyle_Array_Int_Out_Null(iArrNull), "CStyle_Array_Int_Out_Null"); + Assert.IsNull(iArrNull, "CStyle_Array_Int_Out_Null:Equals"); + + Console.WriteLine("CStyle_Array_Int_Out_ZeroLength"); + int[] iArrLength0 = new int[0]; + Assert.IsTrue(CStyle_Array_Int_Out_ZeroLength(iArrLength0), "CStyle_Array_Int_Out_ZeroLength"); + Assert.AreEqual(0, iArrLength0.Length, "CStyle_Array_Int_Out_ZeroLength:Length"); + + Console.WriteLine("CStyle_Array_Uint_Out"); + uint[] uiArr = new uint[ARRAY_SIZE]; + Assert.IsTrue(CStyle_Array_Uint_Out(uiArr, ARRAY_SIZE), "CStyle_Array_Uint_Out"); + Assert.IsTrue(Equals(uiArr, GetExpectedOutArray(ARRAY_SIZE)), "CStyle_Array_Uint_Out:Equals"); + + Console.WriteLine("CStyle_Array_Short_Out"); + short[] sArr = new short[ARRAY_SIZE]; + Assert.IsTrue(CStyle_Array_Short_Out(sArr, ARRAY_SIZE), "CStyle_Array_Short_Out"); + Assert.IsTrue(Equals(sArr, GetExpectedOutArray(ARRAY_SIZE)), "CStyle_Array_Short_Out:Equals"); + + Console.WriteLine("CStyle_Array_Word_Out"); + ushort[] usArr = new ushort[ARRAY_SIZE]; + Assert.IsTrue(CStyle_Array_Word_Out(usArr, ARRAY_SIZE), "CStyle_Array_Word_Out"); + Assert.IsTrue(Equals(usArr, GetExpectedOutArray(ARRAY_SIZE)), "CStyle_Array_Word_Out:Equals"); + + Console.WriteLine("CStyle_Array_Long64_Out"); + long[] lArr = new long[ARRAY_SIZE]; + Assert.IsTrue(CStyle_Array_Long64_Out(lArr, ARRAY_SIZE), "CStyle_Array_Long64_Out"); + Assert.IsTrue(Equals(lArr, GetExpectedOutArray(ARRAY_SIZE)), "CStyle_Array_Long64_Out:Equals"); + + Console.WriteLine("CStyle_Array_ULong64_Out"); + ulong[] ulArr = new ulong[ARRAY_SIZE]; + Assert.IsTrue(CStyle_Array_ULong64_Out(ulArr, ARRAY_SIZE), "CStyle_Array_ULong64_Out"); + Assert.IsTrue(Equals(ulArr, GetExpectedOutArray(ARRAY_SIZE)), "CStyle_Array_ULong64_Out:Equals"); + + Console.WriteLine("CStyle_Array_Double_Out"); + double[] dArr = new double[ARRAY_SIZE]; + Assert.IsTrue(CStyle_Array_Double_Out(dArr, ARRAY_SIZE), "CStyle_Array_Double_Out"); + Assert.IsTrue(Equals(dArr, GetExpectedOutArray(ARRAY_SIZE)), "CStyle_Array_Double_Out:Equals"); + + Console.WriteLine("CStyle_Array_Float_Out"); + float[] fArr = new float[ARRAY_SIZE]; + Assert.IsTrue(CStyle_Array_Float_Out(fArr, ARRAY_SIZE), "CStyle_Array_Float_Out"); + Assert.IsTrue(Equals(fArr, GetExpectedOutArray(ARRAY_SIZE)), "CStyle_Array_Float_Out:Equals"); + + Console.WriteLine("CStyle_Array_Byte_Out"); + byte[] bArr = new byte[ARRAY_SIZE]; + Assert.IsTrue(CStyle_Array_Byte_Out(bArr, ARRAY_SIZE), "CStyle_Array_Byte_Out"); + Assert.IsTrue(Equals(bArr, GetExpectedOutArray(ARRAY_SIZE)), "CStyle_Array_Byte_Out:Equals"); + + Console.WriteLine("CStyle_Array_Char_Out"); + char[] cArr = new char[ARRAY_SIZE]; + Assert.IsTrue(CStyle_Array_Char_Out(cArr, ARRAY_SIZE), "CStyle_Array_Char_Out"); + Assert.IsTrue(Equals(cArr, GetExpectedOutArray(ARRAY_SIZE)), "CStyle_Array_Char_Out:Equals"); + + Console.WriteLine("CStyle_Array_LPSTR_Out"); + string[] strArr = new string[ARRAY_SIZE]; + Assert.IsTrue(CStyle_Array_LPSTR_Out(strArr, ARRAY_SIZE), "CStyle_Array_LPSTR_Out"); + string[] expectedArr = GetExpectedOutArray(ARRAY_SIZE); + // Test nesting null value scenario + expectedArr[expectedArr.Length / 2 - 1] = null; + Assert.IsTrue(Equals(strArr, expectedArr), "CStyle_Array_LPSTR_Out:Equals"); + Console.WriteLine("CStyle_Array_Struct_Out"); + TestStruct[] tsArr = new TestStruct[ARRAY_SIZE]; + Assert.IsTrue(CStyle_Array_Struct_Out(tsArr, ARRAY_SIZE), "CStyle_Array_Struct_Out"); + Assert.IsTrue(Equals(tsArr, GetExpectedOutStructArray(ARRAY_SIZE)), "Equals"); + + Console.WriteLine("CStyle_Array_Bool_Out"); + bool[] boolArr = new bool[ARRAY_SIZE]; + Assert.IsTrue(CStyle_Array_Bool_Out(boolArr, ARRAY_SIZE), "CStyle_Array_Bool_Out"); + Assert.IsTrue(Equals(boolArr, GetExpectedOutBoolArray(ARRAY_SIZE)), "CStyle_Array_Bool_Out:Equals"); + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + Console.WriteLine("CStyle_Array_Object_Out"); + object[] oArr = new object[ARRAY_SIZE]; + Assert.IsTrue(CStyle_Array_Object_Out(oArr, ARRAY_SIZE), "CStyle_Array_Object_Out"); + + object[] expectedOArr = GetExpectedOutArray(ARRAY_SIZE); + // Test nesting null value scenario + expectedOArr[expectedOArr.Length / 2 - 1] = null; + Assert.IsTrue(Equals(oArr, expectedOArr), "CStyle_Array_Object_Out:Equals"); + } + } + + #endregion + + public static int Main() + { + try + { + TestMarshalByVal_NoAttributes(); + TestMarshalByVal_In(); + TestMarshalInOut_ByVal(); + TestMarshalOut_ByVal(); + + Console.WriteLine("\nTest PASS."); + return 100; + } + catch (Exception e) + { + Console.WriteLine($"\nTEST FAIL: {e.Message}"); + return 101; + } + } +} diff --git a/tests/src/Interop/PInvoke/Array/MarshalArrayAsParam/AsDefault/AsDefaultTest.csproj b/tests/src/Interop/PInvoke/Array/MarshalArrayAsParam/AsDefault/AsDefaultTest.csproj new file mode 100644 index 0000000..85a6fd9 --- /dev/null +++ b/tests/src/Interop/PInvoke/Array/MarshalArrayAsParam/AsDefault/AsDefaultTest.csproj @@ -0,0 +1,34 @@ + + + + + Debug + AnyCPU + AsDefaultTest + 2.0 + {F1E66554-8C8E-4141-85CF-D0CD6A0CD0B0} + Exe + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + ..\..\..\..\ + $(DefineConstants);STATIC + + + + + + + False + + + + + + + + + + + + + + diff --git a/tests/src/Interop/PInvoke/Array/MarshalArrayAsParam/AsLPArray/AsLPArrayTest.cs b/tests/src/Interop/PInvoke/Array/MarshalArrayAsParam/AsLPArray/AsLPArrayTest.cs new file mode 100644 index 0000000..e78ce2e --- /dev/null +++ b/tests/src/Interop/PInvoke/Array/MarshalArrayAsParam/AsLPArray/AsLPArrayTest.cs @@ -0,0 +1,650 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; +using TestLibrary; + +public class ArrayMarshal +{ + private static int NumArrOfStructElements1 = 10; + + public struct TestStruct + { + public int x; + public double d; + public long l; + public string str; + } + public struct S2 + { + public int i32; + public uint ui32; + public short s1; + public ushort us1; + public Byte b; + public SByte sb; + public Int16 i16; + public UInt16 ui16; + public Int64 i64; + public UInt64 ui64; + public Single sgl; + public Double d; + } + + #region ByVal PInvoke method with no attributes applied + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Int([MarshalAs(UnmanagedType.LPArray)] int[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Object([MarshalAs(UnmanagedType.LPArray)] object[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Uint([MarshalAs(UnmanagedType.LPArray)] uint[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Short([MarshalAs(UnmanagedType.LPArray)] short[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Word([MarshalAs(UnmanagedType.LPArray)] ushort[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Long64([MarshalAs(UnmanagedType.LPArray)] long[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_ULong64([MarshalAs(UnmanagedType.LPArray)] ulong[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Double([MarshalAs(UnmanagedType.LPArray)] double[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Float([MarshalAs(UnmanagedType.LPArray)] float[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Byte([MarshalAs(UnmanagedType.LPArray)] byte[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Char([MarshalAs(UnmanagedType.LPArray)] char[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_LPCSTR([MarshalAs(UnmanagedType.LPArray)] string[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_LPSTR([MarshalAs(UnmanagedType.LPArray)] string[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Struct([MarshalAs(UnmanagedType.LPArray)] TestStruct[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Bool([MarshalAs(UnmanagedType.LPArray)] bool[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool MarshalArrayOfStructAsLPArrayByVal([MarshalAs(UnmanagedType.LPArray, SizeConst = ARRAY_SIZE)] S2[] arrS2, int cActual, [In, MarshalAs(UnmanagedType.LPArray, SizeConst = ARRAY_SIZE)]S2[] pExpect); + + #endregion + + #region ByVal PInvoke method with InAttribute applied + [DllImport("MarshalArrayLPArrayNative", EntryPoint = "CStyle_Array_Int")] + private static extern bool CStyle_Array_Int_In([In, MarshalAs(UnmanagedType.LPArray)] int[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative", EntryPoint = "CStyle_Array_Object")] + private static extern bool CStyle_Array_Object_In( + [In, MarshalAs(UnmanagedType.LPArray)] object[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative", EntryPoint = "CStyle_Array_Uint")] + private static extern bool CStyle_Array_Uint_In([In, MarshalAs(UnmanagedType.LPArray)] uint[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative", EntryPoint = "CStyle_Array_Short")] + private static extern bool CStyle_Array_Short_In([In, MarshalAs(UnmanagedType.LPArray)] short[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative", EntryPoint = "CStyle_Array_Word")] + private static extern bool CStyle_Array_Word_In([In, MarshalAs(UnmanagedType.LPArray)] ushort[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative", EntryPoint = "CStyle_Array_Long64")] + private static extern bool CStyle_Array_Long64_In([In, MarshalAs(UnmanagedType.LPArray)] long[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative", EntryPoint = "CStyle_Array_ULong64")] + private static extern bool CStyle_Array_ULong64_In([In, MarshalAs(UnmanagedType.LPArray)] ulong[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative", EntryPoint = "CStyle_Array_Double")] + private static extern bool CStyle_Array_Double_In([In, MarshalAs(UnmanagedType.LPArray)] double[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative", EntryPoint = "CStyle_Array_Float")] + private static extern bool CStyle_Array_Float_In([In, MarshalAs(UnmanagedType.LPArray)] float[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative", EntryPoint = "CStyle_Array_Byte")] + private static extern bool CStyle_Array_Byte_In([In, MarshalAs(UnmanagedType.LPArray)] byte[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative", EntryPoint = "CStyle_Array_Char")] + private static extern bool CStyle_Array_Char_In([In, MarshalAs(UnmanagedType.LPArray)] char[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative", EntryPoint = "CStyle_Array_LPCSTR")] + private static extern bool CStyle_Array_LPCSTR_In([In, MarshalAs(UnmanagedType.LPArray)] string[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative", EntryPoint = "CStyle_Array_LPSTR")] + private static extern bool CStyle_Array_LPSTR_In([In, MarshalAs(UnmanagedType.LPArray)] string[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative", EntryPoint = "CStyle_Array_Struct")] + private static extern bool CStyle_Array_Struct_In([In, MarshalAs(UnmanagedType.LPArray)] TestStruct[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative", EntryPoint = "CStyle_Array_Bool")] + private static extern bool CStyle_Array_Bool_In([In, MarshalAs(UnmanagedType.LPArray)] bool[] actual, int cActual); + + + [DllImport("MarshalArrayLPArrayNative", EntryPoint = "MarshalArrayOfStructAsLPArrayByVal")] + private static extern bool MarshalArrayOfStructAsLPArrayByValIn([In, MarshalAs(UnmanagedType.LPArray, SizeConst = ARRAY_SIZE)] S2[] arrS2, int cActual, [In, MarshalAs(UnmanagedType.LPArray, SizeConst = ARRAY_SIZE)]S2[] pExpect); + #endregion + + #region ByVal PInvoke method with InAttribute and OutAttribute applied + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Int_InOut([In, Out, MarshalAs(UnmanagedType.LPArray)] int[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Int_InOut_Null([In, Out, MarshalAs(UnmanagedType.LPArray)] int[] actual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Int_InOut_ZeroLength([In, Out, MarshalAs(UnmanagedType.LPArray)] int[] actual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Object_InOut([In, Out, MarshalAs(UnmanagedType.LPArray)] object[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Uint_InOut([In, Out, MarshalAs(UnmanagedType.LPArray)] uint[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Short_InOut([In, Out, MarshalAs(UnmanagedType.LPArray)] short[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Word_InOut([In, Out, MarshalAs(UnmanagedType.LPArray)] ushort[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Long64_InOut([In, Out, MarshalAs(UnmanagedType.LPArray)] long[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_ULong64_InOut([In, Out, MarshalAs(UnmanagedType.LPArray)] ulong[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Double_InOut([In, Out, MarshalAs(UnmanagedType.LPArray)] double[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Float_InOut([In, Out, MarshalAs(UnmanagedType.LPArray)] float[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Byte_InOut([In, Out, MarshalAs(UnmanagedType.LPArray)] byte[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Char_InOut([In, Out, MarshalAs(UnmanagedType.LPArray)] char[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_LPSTR_InOut([In, Out, MarshalAs(UnmanagedType.LPArray)] string[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Struct_InOut([In, Out, MarshalAs(UnmanagedType.LPArray)] TestStruct[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Bool_InOut([In, Out, MarshalAs(UnmanagedType.LPArray)] bool[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool MarshalArrayOfStructAsLPArrayByValInOut([In, Out, MarshalAs(UnmanagedType.LPArray, SizeConst = ARRAY_SIZE)] S2[] arrS2, int cActual, [In, MarshalAs(UnmanagedType.LPArray, SizeConst = ARRAY_SIZE)]S2[] pExpect); + + #endregion + + #region ByVal PInvoke method with OutAttribute applied + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Int_Out([Out, MarshalAs(UnmanagedType.LPArray)] int[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Int_Out_Null([Out, MarshalAs(UnmanagedType.LPArray)] int[] actual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Int_Out_ZeroLength([Out, MarshalAs(UnmanagedType.LPArray)] int[] actual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Object_Out([Out, MarshalAs(UnmanagedType.LPArray)] object[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Uint_Out([Out, MarshalAs(UnmanagedType.LPArray)] uint[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Short_Out([Out, MarshalAs(UnmanagedType.LPArray)] short[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Word_Out([Out, MarshalAs(UnmanagedType.LPArray)] ushort[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Long64_Out([Out, MarshalAs(UnmanagedType.LPArray)] long[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_ULong64_Out([Out, MarshalAs(UnmanagedType.LPArray)] ulong[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Double_Out([Out, MarshalAs(UnmanagedType.LPArray)] double[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Float_Out([Out, MarshalAs(UnmanagedType.LPArray)] float[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Byte_Out([Out, MarshalAs(UnmanagedType.LPArray)] byte[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Char_Out([Out, MarshalAs(UnmanagedType.LPArray)] char[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_LPSTR_Out([Out, MarshalAs(UnmanagedType.LPArray)] string[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Struct_Out([Out, MarshalAs(UnmanagedType.LPArray)] TestStruct[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool CStyle_Array_Bool_Out([Out, MarshalAs(UnmanagedType.LPArray)] bool[] actual, int cActual); + + [DllImport("MarshalArrayLPArrayNative")] + private static extern bool MarshalArrayOfStructAsLPArrayByValOut([Out, MarshalAs(UnmanagedType.LPArray, SizeConst = ARRAY_SIZE)] S2[] arrS2, int cActual); + + #endregion + + #region Marshal ByVal + private const int ARRAY_SIZE = 100; + + private static T[] InitArray(int size) + { + T[] array = new T[size]; + + for (int i = 0; i < array.Length; ++i) + array[i] = (T)Convert.ChangeType(i, typeof(T)); + + return array; + } + + private static T[] CopyArray(T[] srcarr, int size) + { + T[] array = new T[size]; + + Array.Copy(srcarr, array, ARRAY_SIZE); + return array; + } + + private static bool[] InitBoolArray(int size) + { + bool[] array = new bool[size]; + + for (int i = 0; i < array.Length; ++i) + { + if (i % 2 == 0) + array[i] = true; + else + array[i] = false; + } + + return array; + } + + private static TestStruct[] InitStructArray(int size) + { + TestStruct[] array = new TestStruct[size]; + + for (int i = 0; i < array.Length; ++i) + { + array[i].x = i; + array[i].d = i; + array[i].l = i; + array[i].str = i.ToString(); + } + + return array; + } + private static void TestMarshalByVal_NoAttributes() + { + Console.WriteLine("ByVal marshaling CLR array as c-style-array no attributes"); + + Assert.IsTrue(CStyle_Array_Int(InitArray(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Int"); + Assert.IsTrue(CStyle_Array_Uint(InitArray(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Uint"); + Assert.IsTrue(CStyle_Array_Short(InitArray(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Short"); + Assert.IsTrue(CStyle_Array_Word(InitArray(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Word"); + Assert.IsTrue(CStyle_Array_Long64(InitArray(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Long64"); + Assert.IsTrue(CStyle_Array_ULong64(InitArray(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_ULong64"); + Assert.IsTrue(CStyle_Array_Double(InitArray(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Double"); + Assert.IsTrue(CStyle_Array_Float(InitArray(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Float"); + Assert.IsTrue(CStyle_Array_Byte(InitArray(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Byte"); + Assert.IsTrue(CStyle_Array_Char(InitArray(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Char"); + + string[] strArr = InitArray(ARRAY_SIZE); + // Test nesting null value scenario + strArr[strArr.Length / 2] = null; + Assert.IsTrue(CStyle_Array_LPCSTR(strArr, ARRAY_SIZE), "CStyle_Array_LPCSTR"); + Assert.IsTrue(CStyle_Array_LPSTR(strArr, ARRAY_SIZE), "CStyle_Array_LPSTRs"); + Assert.IsTrue(CStyle_Array_Struct(InitStructArray(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Struct"); + Assert.IsTrue(CStyle_Array_Bool(InitBoolArray(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Bool"); + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + object[] oArr = InitArray(ARRAY_SIZE); + // Test nesting null value scenario + oArr[oArr.Length / 2] = null; + Assert.IsTrue(CStyle_Array_Object(oArr, ARRAY_SIZE), "CStyle_Array_Object"); + } + + } + + private static void TestMarshalByVal_In() + { + Console.WriteLine("ByVal marshaling CLR array as c-style-array with InAttribute applied"); + + Assert.IsTrue(CStyle_Array_Int_In(InitArray(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Int_In"); + Assert.IsTrue(CStyle_Array_Uint_In(InitArray(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Uint_In"); + Assert.IsTrue(CStyle_Array_Short_In(InitArray(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Short_In"); + Assert.IsTrue(CStyle_Array_Word_In(InitArray(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Word_In"); + Assert.IsTrue(CStyle_Array_Long64_In(InitArray(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Long64_In"); + Assert.IsTrue(CStyle_Array_ULong64_In(InitArray(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_ULong64_In"); + Assert.IsTrue(CStyle_Array_Double_In(InitArray(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Double_In"); + Assert.IsTrue(CStyle_Array_Float_In(InitArray(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Float_In"); + Assert.IsTrue(CStyle_Array_Byte_In(InitArray(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Byte_In"); + Assert.IsTrue(CStyle_Array_Char_In(InitArray(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Char_In"); + + string[] strArr = InitArray(ARRAY_SIZE); + // Test nesting null value scenario + strArr[strArr.Length / 2] = null; + Assert.IsTrue(CStyle_Array_LPCSTR_In(strArr, ARRAY_SIZE), "CStyle_Array_LPCSTR_In"); + Assert.IsTrue(CStyle_Array_LPSTR_In(strArr, ARRAY_SIZE), "CStyle_Array_LPSTR_In"); + Assert.IsTrue(CStyle_Array_Struct_In(InitStructArray(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Struct_In"); + Assert.IsTrue(CStyle_Array_Bool_In(InitBoolArray(ARRAY_SIZE), ARRAY_SIZE), "CStyle_Array_Bool_In"); + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + object[] oArr = InitArray(ARRAY_SIZE); + // Test nesting null value scenario + oArr[oArr.Length / 2] = null; + Assert.IsTrue(CStyle_Array_Object_In(oArr, ARRAY_SIZE), "CStyle_Array_Object_In"); + } + } + #endregion + + #region Marshal InOut ByVal + private static void TestMarshalByVal_InOut() + { + Console.WriteLine("By value marshaling CLR array as c-style-array with InAttribute and OutAttribute applied"); + int[] iArr = InitArray(ARRAY_SIZE); + Assert.IsTrue(CStyle_Array_Int_InOut(iArr, ARRAY_SIZE), "CStyle_Array_Int_InOut"); + Assert.IsTrue(Equals(iArr, GetExpectedOutArray(ARRAY_SIZE)), "CStyle_Array_Int_InOut:Equals"); + + int[] iArrNull = null; + Assert.IsTrue(CStyle_Array_Int_InOut_Null(iArrNull), "CStyle_Array_Int_InOut_Null"); + Assert.IsNull(iArrNull, "CStyle_Array_Int_InOut_Null:Equals"); + + int[] iArrLength0 = InitArray(0); + Assert.IsTrue(CStyle_Array_Int_InOut_ZeroLength(iArrLength0), "CStyle_Array_Int_InOut_ZeroLength"); + Assert.AreEqual(0, iArrLength0.Length, "CStyle_Array_Int_InOut_ZeroLength:Length"); + + uint[] uiArr = InitArray(ARRAY_SIZE); + Assert.IsTrue(CStyle_Array_Uint_InOut(uiArr, ARRAY_SIZE), "CStyle_Array_Uint_InOut"); + Assert.IsTrue(Equals(uiArr, GetExpectedOutArray(ARRAY_SIZE)), "CStyle_Array_Uint_InOut:Equals"); + + short[] sArr = InitArray(ARRAY_SIZE); + Assert.IsTrue(CStyle_Array_Short_InOut(sArr, ARRAY_SIZE), "CStyle_Array_Short_InOut"); + Assert.IsTrue(Equals(sArr, GetExpectedOutArray(ARRAY_SIZE)), "CStyle_Array_Short_InOut:Equals"); + + ushort[] usArr = InitArray(ARRAY_SIZE); + Assert.IsTrue(CStyle_Array_Word_InOut(usArr, ARRAY_SIZE), "CStyle_Array_Word_InOut"); + Assert.IsTrue(Equals(usArr, GetExpectedOutArray(ARRAY_SIZE)), "CStyle_Array_Word_InOut:Equals"); + + long[] lArr = InitArray(ARRAY_SIZE); + Assert.IsTrue(CStyle_Array_Long64_InOut(lArr, ARRAY_SIZE), "CStyle_Array_Long64_InOut"); + Assert.IsTrue(Equals(lArr, GetExpectedOutArray(ARRAY_SIZE)), "CStyle_Array_Long64_InOut:Equals"); + + ulong[] ulArr = InitArray(ARRAY_SIZE); + Assert.IsTrue(CStyle_Array_ULong64_InOut(ulArr, ARRAY_SIZE), "CStyle_Array_ULong64_InOut"); + Assert.IsTrue(Equals(ulArr, GetExpectedOutArray(ARRAY_SIZE)), "CStyle_Array_ULong64_InOut:Equals"); + + double[] dArr = InitArray(ARRAY_SIZE); + Assert.IsTrue(CStyle_Array_Double_InOut(dArr, ARRAY_SIZE), "CStyle_Array_Double_InOut"); + Assert.IsTrue(Equals(dArr, GetExpectedOutArray(ARRAY_SIZE)), "CStyle_Array_Double_InOut:Equals"); + + float[] fArr = InitArray(ARRAY_SIZE); + Assert.IsTrue(CStyle_Array_Float_InOut(fArr, ARRAY_SIZE), "CStyle_Array_Float_InOut"); + Assert.IsTrue(Equals(fArr, GetExpectedOutArray(ARRAY_SIZE)), "CStyle_Array_Float_InOut:Equals"); + + byte[] bArr = InitArray(ARRAY_SIZE); + Assert.IsTrue(CStyle_Array_Byte_InOut(bArr, ARRAY_SIZE), "CStyle_Array_Byte_InOut"); + Assert.IsTrue(Equals(bArr, GetExpectedOutArray(ARRAY_SIZE)), "CStyle_Array_Byte_InOut:Equals"); + + char[] cArr = InitArray(ARRAY_SIZE); + Assert.IsTrue(CStyle_Array_Char_InOut(cArr, ARRAY_SIZE), "CStyle_Array_Char_InOut"); + Assert.IsTrue(Equals(cArr, GetExpectedOutArray(ARRAY_SIZE)), "CStyle_Array_Char_InOut:Equals"); + + string[] strArr = InitArray(ARRAY_SIZE); + strArr[strArr.Length / 2] = null; + Assert.IsTrue(CStyle_Array_LPSTR_InOut(strArr, ARRAY_SIZE), "CStyle_Array_LPSTR_InOut"); + + string[] expectedArr = GetExpectedOutArray(ARRAY_SIZE); + // Test nesting null value scenario + expectedArr[expectedArr.Length / 2 - 1] = null; + Assert.IsTrue(Equals(strArr, expectedArr), "CStyle_Array_LPSTR_InOut:Equals"); + + TestStruct[] tsArr = InitStructArray(ARRAY_SIZE); + Assert.IsTrue(CStyle_Array_Struct_InOut(tsArr, ARRAY_SIZE), "CStyle_Array_Struct_InOut"); + Assert.IsTrue(Equals(tsArr, GetExpectedOutStructArray(ARRAY_SIZE)), "CStyle_Array_Struct_InOut:Equals"); + + bool[] boolArr = InitBoolArray(ARRAY_SIZE); + Assert.IsTrue(CStyle_Array_Bool_InOut(boolArr, ARRAY_SIZE), "CStyle_Array_Bool_InOut"); + Assert.IsTrue(Equals(boolArr, GetExpectedOutBoolArray(ARRAY_SIZE)), "CStyle_Array_Bool_InOut:Equals"); + } + + private static bool Equals(T[] arr1, T[] arr2) + { + if (arr1 == null && arr2 == null) + return true; + else if (arr1 == null && arr2 != null) + return false; + else if (arr1 != null && arr2 == null) + return false; + else if (arr1.Length != arr2.Length) + return false; + + for (int i = 0; i < arr2.Length; ++i) + { + if (!Object.Equals(arr1[i], arr2[i])) + { + Console.WriteLine("Array marshaling error, Index: {0} , Expected:{1}, Actual:{2}", i, arr2[i], arr1[i]); + return false; + } + } + return true; + } + + private static T[] GetExpectedOutArray(int size) + { + T[] array = new T[size]; + for (int i = array.Length - 1; i >= 0; --i) + array[i] = (T)Convert.ChangeType(array.Length - 1 - i, typeof(T)); + return array; + } + + private static bool[] GetExpectedOutBoolArray(int size) + { + bool[] array = new bool[size]; + for (int i = 0; i < array.Length; ++i) + { + if (i % 2 != 0) + array[i] = true; + else + array[i] = false; + } + return array; + } + + private static TestStruct[] GetExpectedOutStructArray(int size) + { + TestStruct[] array = new TestStruct[size]; + for (int i = array.Length - 1; i >= 0; --i) + { + int v = array.Length - 1 - i; + array[i].x = v; + array[i].d = v; + array[i].l = v; + array[i].str = v.ToString(); + } + return array; + } + #endregion + + #region Marshal InOut ByVal + private static void TestMarshalByVal_Out() + { + Console.WriteLine("By value marshaling CLR array as c-style-array with OutAttribute applied"); + + int[] iArr = new int[ARRAY_SIZE]; + Assert.IsTrue(CStyle_Array_Int_Out(iArr, ARRAY_SIZE), "CStyle_Array_Int_Out"); + Assert.IsTrue(Equals(iArr, GetExpectedOutArray(ARRAY_SIZE)), "CStyle_Array_Int_Out:Equals"); + + int[] iArrNull = null; + Assert.IsTrue(CStyle_Array_Int_Out_Null(iArrNull), "CStyle_Array_Int_Out_Null"); + Assert.IsNull(iArrNull, "CStyle_Array_Int_Out_Null:Equals"); + + int[] iArrLength0 = new int[0]; + Assert.IsTrue(CStyle_Array_Int_Out_ZeroLength(iArrLength0), "CStyle_Array_Int_Out_ZeroLength"); + Assert.AreEqual(0, iArrLength0.Length, "CStyle_Array_Int_Out_ZeroLength:Length"); + + uint[] uiArr = new uint[ARRAY_SIZE]; + Assert.IsTrue(CStyle_Array_Uint_Out(uiArr, ARRAY_SIZE), "CStyle_Array_Uint_Out"); + Assert.IsTrue(Equals(uiArr, GetExpectedOutArray(ARRAY_SIZE)), "CStyle_Array_Uint_Out:Equals"); + + short[] sArr = new short[ARRAY_SIZE]; + Assert.IsTrue(CStyle_Array_Short_Out(sArr, ARRAY_SIZE), "CStyle_Array_Short_Out"); + Assert.IsTrue(Equals(sArr, GetExpectedOutArray(ARRAY_SIZE)), "CStyle_Array_Short_Out:Equals"); + + ushort[] usArr = new ushort[ARRAY_SIZE]; + Assert.IsTrue(CStyle_Array_Word_Out(usArr, ARRAY_SIZE), "CStyle_Array_Word_Out"); + Assert.IsTrue(Equals(usArr, GetExpectedOutArray(ARRAY_SIZE)), "CStyle_Array_Word_Out:Equals"); + + long[] lArr = new long[ARRAY_SIZE]; + Assert.IsTrue(CStyle_Array_Long64_Out(lArr, ARRAY_SIZE), "CStyle_Array_Long64_Out"); + Assert.IsTrue(Equals(lArr, GetExpectedOutArray(ARRAY_SIZE)), "CStyle_Array_Long64_Out:Equals"); + + ulong[] ulArr = new ulong[ARRAY_SIZE]; + Assert.IsTrue(CStyle_Array_ULong64_Out(ulArr, ARRAY_SIZE), "CStyle_Array_ULong64_Out"); + Assert.IsTrue(Equals(ulArr, GetExpectedOutArray(ARRAY_SIZE)), "CStyle_Array_ULong64_Out:Equals"); + + double[] dArr = new double[ARRAY_SIZE]; + Assert.IsTrue(CStyle_Array_Double_Out(dArr, ARRAY_SIZE), "CStyle_Array_Double_Out"); + Assert.IsTrue(Equals(dArr, GetExpectedOutArray(ARRAY_SIZE)), "CStyle_Array_Double_Out:Equals"); + + float[] fArr = new float[ARRAY_SIZE]; + Assert.IsTrue(CStyle_Array_Float_Out(fArr, ARRAY_SIZE), "CStyle_Array_Float_Out"); + Assert.IsTrue(Equals(fArr, GetExpectedOutArray(ARRAY_SIZE)), "CStyle_Array_Float_Out:Equals"); + + byte[] bArr = new byte[ARRAY_SIZE]; + Assert.IsTrue(CStyle_Array_Byte_Out(bArr, ARRAY_SIZE), "CStyle_Array_Byte_Out"); + Assert.IsTrue(Equals(bArr, GetExpectedOutArray(ARRAY_SIZE)), "CStyle_Array_Byte_Out:Equals"); + + char[] cArr = new char[ARRAY_SIZE]; + Assert.IsTrue(CStyle_Array_Char_Out(cArr, ARRAY_SIZE), "CStyle_Array_Char_Out"); + Assert.IsTrue(Equals(cArr, GetExpectedOutArray(ARRAY_SIZE)), "CStyle_Array_Char_Out:Equals"); + + string[] strArr = new string[ARRAY_SIZE]; + Assert.IsTrue(CStyle_Array_LPSTR_Out(strArr, ARRAY_SIZE), "CStyle_Array_LPSTR_Out"); + + string[] expectedArr = GetExpectedOutArray(ARRAY_SIZE); + // Test nesting null value scenario + expectedArr[expectedArr.Length / 2 - 1] = null; + Assert.IsTrue(Equals(strArr, expectedArr), "CStyle_Array_LPSTR_Out:Equals"); + + TestStruct[] tsArr = new TestStruct[ARRAY_SIZE]; + Assert.IsTrue(CStyle_Array_Struct_Out(tsArr, ARRAY_SIZE), "CStyle_Array_Struct_Out"); + Assert.IsTrue(Equals(tsArr, GetExpectedOutStructArray(ARRAY_SIZE)), "CStyle_Array_Struct_Out:Equals"); + + bool[] boolArr = new bool[ARRAY_SIZE]; + Assert.IsTrue(CStyle_Array_Bool_Out(boolArr, ARRAY_SIZE), "CStyle_Array_Bool_Out"); + Assert.IsTrue(Equals(boolArr, GetExpectedOutBoolArray(ARRAY_SIZE)), "CStyle_Array_Bool_Out:Equals"); + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + object[] oArr = new object[ARRAY_SIZE]; + Assert.IsTrue(CStyle_Array_Object_Out(oArr, ARRAY_SIZE), "CStyle_Array_Object_Out"); + object[] expectedOArr = GetExpectedOutArray(ARRAY_SIZE); + // Test nesting null value scenario + expectedOArr[expectedOArr.Length / 2 - 1] = null; + Assert.IsTrue(Equals(oArr, expectedOArr), "CStyle_Array_Object_Out:Equals"); + } + + } + #endregion + + #region methods for S2 struct array + public static S2[] NewS2arr(int NumArrElements, int i32, uint ui32, short s1, ushort us1, + Byte b, SByte sb, Int16 i16, UInt16 ui16, Int64 i64, UInt64 ui64, Single sgl, Double d) + { + S2[] arrS2 = new S2[NumArrElements]; + for (int i = 0; i < NumArrElements; i++) + { + arrS2[i].i32 = i32; + arrS2[i].ui32 = ui32; + arrS2[i].s1 = s1; + arrS2[i].us1 = us1; + arrS2[i].b = b; + arrS2[i].sb = sb; + arrS2[i].i16 = i16; + arrS2[i].ui16 = ui16; + arrS2[i].i64 = i64; + arrS2[i].ui64 = ui64; + arrS2[i].sgl = sgl; + arrS2[i].d = d; + } + return arrS2; + } + public static void PrintS2arr(string name, S2[] arrS2) + { + for (int i = 0; i < arrS2.Length; i++) + { + Console.WriteLine("{0}[{1}].i32 = {2}", name, i, arrS2[i].i32); + Console.WriteLine("{0}[{1}].ui32 = {2}", name, i, arrS2[i].ui32); + Console.WriteLine("{0}[{1}].s1 = {2}", name, i, arrS2[i].s1); + Console.WriteLine("{0}[{1}].us1 = {2}", name, i, arrS2[i].us1); + Console.WriteLine("{0}[{1}].b = {2}", name, i, arrS2[i].b); + Console.WriteLine("{0}[{1}].sb = {2}", name, i, arrS2[i].sb); + Console.WriteLine("{0}[{1}].i16 = {2}", name, i, arrS2[i].i16); + Console.WriteLine("{0}[{1}].ui16 = {2}", name, i, arrS2[i].ui16); + Console.WriteLine("{0}[{1}].i64 = {2}", name, i, arrS2[i].i64); + Console.WriteLine("{0}[{1}].ui64 = {2}", name, i, arrS2[i].ui64); + Console.WriteLine("{0}[{1}].sgl = {2}", name, i, arrS2[i].sgl); + Console.WriteLine("{0}[{1}].d = {2}", name, i, arrS2[i].d); + } + } + public static bool IsCorrect(S2[] actual, S2[] expected) + { + if (actual.Length != expected.Length) + { + return false; + } + for (int i = 0; i < actual.Length; i++) + { + if (actual[i].i32 != expected[i].i32 || actual[i].ui32 != expected[i].ui32 || actual[i].s1 != expected[i].s1 || actual[i].us1 != expected[i].us1 || + actual[i].b != expected[i].b || actual[i].sb != expected[i].sb || actual[i].i16 != expected[i].i16 || + actual[i].ui16 != expected[i].ui16 || actual[i].i64 != expected[i].i64 || actual[i].ui64 != expected[i].ui64 || + actual[i].sgl != expected[i].sgl || actual[i].d != expected[i].d) + { + return false; + } + } + return true; + } + #endregion + + public static int Main() + { + try{ + TestMarshalByVal_NoAttributes(); + TestMarshalByVal_In(); + TestMarshalByVal_InOut(); + TestMarshalByVal_Out(); + + Console.WriteLine("\nTest PASS."); + return 100; + } + catch (Exception e) + { + Console.WriteLine($"\nTEST FAIL: {e.Message}"); + return 101; + } + } +} diff --git a/tests/src/Interop/PInvoke/Array/MarshalArrayAsParam/AsLPArray/AsLPArrayTest.csproj b/tests/src/Interop/PInvoke/Array/MarshalArrayAsParam/AsLPArray/AsLPArrayTest.csproj new file mode 100644 index 0000000..47dec3c --- /dev/null +++ b/tests/src/Interop/PInvoke/Array/MarshalArrayAsParam/AsLPArray/AsLPArrayTest.csproj @@ -0,0 +1,34 @@ + + + + + Debug + AnyCPU + AsLPArrayTest + 2.0 + {F1E66554-8C8E-4141-85CF-D0CD6A0CD0B0} + Exe + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + ..\..\..\..\ + $(DefineConstants);STATIC + + + + + + + False + + + + + + + + + + + + + + diff --git a/tests/src/Interop/PInvoke/Array/MarshalArrayAsParam/LPArrayNative/CMakeLists.txt b/tests/src/Interop/PInvoke/Array/MarshalArrayAsParam/LPArrayNative/CMakeLists.txt new file mode 100644 index 0000000..6f27e1c --- /dev/null +++ b/tests/src/Interop/PInvoke/Array/MarshalArrayAsParam/LPArrayNative/CMakeLists.txt @@ -0,0 +1,15 @@ +#VCXPROJ +cmake_minimum_required (VERSION 2.6) +project (MarshalArrayLPArrayNative) +include ("${CLR_INTEROP_TEST_ROOT}/Interop.cmake") +include_directories("../..") +include_directories(${INC_PLATFORM_DIR}) +set(SOURCES + MarshalArrayLPArrayNative.cpp +) + +# add the executable +add_library (MarshalArrayLPArrayNative SHARED ${SOURCES}) +target_link_libraries(MarshalArrayLPArrayNative ${LINK_LIBRARIES_ADDITIONAL}) +# add the install targets +install (TARGETS MarshalArrayLPArrayNative DESTINATION bin) diff --git a/tests/src/Interop/PInvoke/Array/MarshalArrayAsParam/LPArrayNative/MarshalArrayLPArrayNative.cpp b/tests/src/Interop/PInvoke/Array/MarshalArrayAsParam/LPArrayNative/MarshalArrayLPArrayNative.cpp new file mode 100644 index 0000000..dc42224 --- /dev/null +++ b/tests/src/Interop/PInvoke/Array/MarshalArrayAsParam/LPArrayNative/MarshalArrayLPArrayNative.cpp @@ -0,0 +1,1107 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#include +#include "MarshalArray.h" + +template +bool Equals(T *pActual, int cActual, T *pExpected, int cExpected) +{ + if (pActual == NULL && pExpected == NULL) + return true; + else if (pActual == NULL && pExpected != NULL) + return false; + else if (pActual != NULL && pExpected == NULL) + return false; + else if (cActual != cExpected) + return false; + + for (int i = 0; i < cExpected; ++i) + { + if (!IsObjectEquals(pActual[i], pExpected[i])) + { + printf("WARNING: Test error - %s\n", __FUNCSIG__); + return false; + } + } + + return true; +} + +#define EQUALS(__actual, __cActual, __expected) Equals((__actual), (__cActual), (__expected), (int)sizeof(__expected) / sizeof(__expected[0])) +#define INIT_EXPECTED(__type, __size) \ + __type expected[(__size)]; \ +for (size_t i = 0; i < (__size); ++i) \ + expected[i] = (__type)i + +/////////////////////////////////////////// By Value ///////////////////////////////////////// +extern "C" DLL_EXPORT BOOL CStyle_Array_Int(int *pActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(pActual); + + INIT_EXPECTED(int, ARRAY_SIZE); + + return EQUALS(pActual, cActual, expected); +} + +#ifdef _WIN32 +extern "C" DLL_EXPORT BOOL CStyle_Array_Object(VARIANT *pActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(pActual); + + //VARIANT expected[ARRAY_SIZE]; + size_t nullIdx = ARRAY_SIZE / 2; + + for (size_t i = 0; i < ARRAY_SIZE; ++i) + { + //VariantInit(&expected[i]); + if (i == nullIdx) + { + if ((pActual[i].vt != VT_EMPTY)) + { + printf("=====EMPTY VALUE NOT FOUND==== %s\n", __FUNCTION__); + return FALSE; + } + else + { + continue; + } + } + if ((pActual[i].vt != VT_I4) && ((size_t)(pActual[i].lVal) != i)) + { + printf("====VARIANTS NOT EQUAL==== %s\n", __FUNCTION__); + return TRUE; + } + } + + return TRUE; + //EQUALS(pActual, cActual, expected); +} +#endif + +extern "C" DLL_EXPORT BOOL CStyle_Array_Uint(UINT *pActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(pActual); + + INIT_EXPECTED(UINT, ARRAY_SIZE); + + return EQUALS(pActual, cActual, expected); +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Short(SHORT *pActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(pActual); + + INIT_EXPECTED(SHORT, ARRAY_SIZE); + + return EQUALS(pActual, cActual, expected); +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Word(WORD *pActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(pActual); + + INIT_EXPECTED(WORD, ARRAY_SIZE); + + return EQUALS(pActual, cActual, expected); +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Long64(LONG64 *pActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(pActual); + + INIT_EXPECTED(LONG64, ARRAY_SIZE); + + return EQUALS(pActual, cActual, expected); +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_ULong64(ULONG64 *pActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(pActual); + + INIT_EXPECTED(ULONG64, ARRAY_SIZE); + + return EQUALS(pActual, cActual, expected); +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Double(DOUBLE *pActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(pActual); + + INIT_EXPECTED(DOUBLE, ARRAY_SIZE); + + return EQUALS(pActual, cActual, expected); +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Float(FLOAT *pActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(pActual); + + INIT_EXPECTED(FLOAT, ARRAY_SIZE); + + return EQUALS(pActual, cActual, expected); +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Byte(BYTE *pActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(pActual); + + INIT_EXPECTED(BYTE, ARRAY_SIZE); + + return EQUALS(pActual, cActual, expected); +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Char(CHAR *pActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(pActual); + + INIT_EXPECTED(CHAR, ARRAY_SIZE); + + return EQUALS(pActual, cActual, expected); +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_LPCSTR(LPCSTR *pActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(pActual); + + LPSTR expected[ARRAY_SIZE]; + size_t nullIdx = ARRAY_SIZE / 2; + for (size_t i = 0; i < ARRAY_SIZE; ++i) + { + if (i == nullIdx) + { + expected[i] = NULL; + continue; + } + expected[i] = ToString((int)i); + } + + int retval = EQUALS((LPSTR *)pActual, cActual, expected); + + for (size_t i = 0; i < ARRAY_SIZE; ++i) + { + if (i == nullIdx) + continue; + + CoreClrFree(expected[i]); + } + + return retval; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_LPSTR(LPSTR *pActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(pActual); + + return CStyle_Array_LPCSTR((LPCSTR *)pActual, cActual); +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Struct(TestStruct *pActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(pActual); + + TestStruct expected[ARRAY_SIZE]; + for (size_t i = 0; i < ARRAY_SIZE; ++i) + { + expected[i].x = (int)i; + expected[i].d = (int)i; + expected[i].l = (LONG64)i; + expected[i].str = ToString((int)i); + } + + return EQUALS(pActual, cActual, expected); +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Bool(BOOL *pActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(pActual); + + BOOL expected[ARRAY_SIZE]; + for (size_t i = 0; i < ARRAY_SIZE; ++i) + { + if (i % 2 == 0) + expected[i] = TRUE; + else + expected[i] = FALSE; + } + + return EQUALS(pActual, cActual, expected); +} + +/////////////////////////////////////////// In Out By Value ///////////////////////////////////////// +template +void ChangeArrayValue(T *pArray, int cSize) +{ + for (int i = 0; i < cSize; ++i) + pArray[i] = (T)(cSize - 1 - i); +} + +template<> +void ChangeArrayValue(LPSTR *pArray, int cSize) +{ + for (int i = 0; i < cSize; ++i) + { + // Free resource + CoreClrFree(pArray[i]); + pArray[i] = ToString(cSize - 1 - i); + } + + int nullIdx = cSize / 2 - 1; + CoreClrFree(pArray[nullIdx]); + pArray[nullIdx] = NULL; +} + +template<> +void ChangeArrayValue(LPCSTR *pArray, int cSize) +{ + for (int i = 0; i < cSize; ++i) + { + // Free resource + CoreClrFree((LPVOID)pArray[i]); + pArray[i] = ToString(cSize - 1 - i); + } + + int nullIdx = cSize / 2 - 1; + CoreClrFree((LPVOID)pArray[nullIdx]); + pArray[nullIdx] = NULL; +} + +#ifdef _WIN32 +template<> +void ChangeArrayValue(VARIANT *pArray, int cSize) +{ + for (int i = 0; i < cSize; ++i) + { + // Free resource + VariantClear(&pArray[i]); + pArray[i].vt = VT_I4; + pArray[i].lVal = cSize - 1 - i; + } + + int nullIdx = cSize / 2 - 1; + VariantClear(&pArray[nullIdx]); + pArray[nullIdx].vt = VT_EMPTY; +} +#endif + +template<> +void ChangeArrayValue(TestStruct *pArray, int cSize) +{ + for (int i = 0; i < cSize; ++i) + { + int v = (cSize - 1 - i); + pArray[i].x = v; + pArray[i].d = v; + pArray[i].l = v; + pArray[i].str = ToString(v); + } +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Int_InOut(int *pActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(pActual); + + BOOL retval = CStyle_Array_Int(pActual, cActual); + ChangeArrayValue(pActual, cActual); + + return retval; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Int_InOut_Null(int *pActual) +{ + CHECK_PARAM_EMPTY(pActual); + return true; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Int_InOut_ZeroLength(int *pActual) +{ + CHECK_PARAM_NOT_EMPTY(pActual); + return true; +} + +#ifdef _WIN32 +extern "C" DLL_EXPORT BOOL CStyle_Array_Object_InOut(VARIANT *pActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(pActual); + + BOOL retval = CStyle_Array_Object(pActual, cActual); + ChangeArrayValue(pActual, cActual); + + return retval; +} +#endif + +extern "C" DLL_EXPORT BOOL CStyle_Array_Uint_InOut(UINT *pActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(pActual); + + BOOL retval = CStyle_Array_Uint(pActual, cActual); + ChangeArrayValue(pActual, cActual); + + return retval; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Short_InOut(SHORT *pActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(pActual); + + BOOL retval = CStyle_Array_Short(pActual, cActual); + ChangeArrayValue(pActual, cActual); + + return retval; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Word_InOut(WORD *pActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(pActual); + + BOOL retval = CStyle_Array_Word(pActual, cActual); + ChangeArrayValue(pActual, cActual); + + return retval; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Long64_InOut(LONG64 *pActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(pActual); + + BOOL retval = CStyle_Array_Long64(pActual, cActual); + ChangeArrayValue(pActual, cActual); + + return retval; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_ULong64_InOut(ULONG64 *pActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(pActual); + + BOOL retval = CStyle_Array_ULong64(pActual, cActual); + ChangeArrayValue(pActual, cActual); + + return retval; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Double_InOut(DOUBLE *pActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(pActual); + + BOOL retval = CStyle_Array_Double(pActual, cActual); + ChangeArrayValue(pActual, cActual); + + return retval; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Float_InOut(FLOAT *pActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(pActual); + + BOOL retval = CStyle_Array_Float(pActual, cActual); + ChangeArrayValue(pActual, cActual); + + return retval; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Byte_InOut(BYTE *pActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(pActual); + + BOOL retval = CStyle_Array_Byte(pActual, cActual); + ChangeArrayValue(pActual, cActual); + + return retval; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Char_InOut(CHAR *pActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(pActual); + + BOOL retval = CStyle_Array_Char(pActual, cActual); + ChangeArrayValue(pActual, cActual); + + return retval; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_LPSTR_InOut(LPSTR *pActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(pActual); + + BOOL retval = CStyle_Array_LPSTR(pActual, cActual); + ChangeArrayValue(pActual, cActual); + + return retval; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Struct_InOut(TestStruct *pActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(pActual); + + BOOL retval = CStyle_Array_Struct(pActual, cActual); + ChangeArrayValue(pActual, cActual); + + return retval; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Bool_InOut(BOOL *pActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(pActual); + + BOOL retval = CStyle_Array_Bool(pActual, cActual); + + for (int i = 0; i < cActual; ++i) + { + if (i % 2 != 0) + pActual[i] = TRUE; + else + pActual[i] = FALSE; + } + + return retval; +} + +/////////////////////////////////////////// Out By Value ///////////////////////////////////////// +extern "C" DLL_EXPORT BOOL CStyle_Array_Int_Out(int *pActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(pActual); + + ChangeArrayValue(pActual, cActual); + + return true; +} +extern "C" DLL_EXPORT BOOL CStyle_Array_Int_Out_Null(int *pActual) +{ + CHECK_PARAM_EMPTY(pActual); + return true; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Int_Out_ZeroLength(int *pActual) +{ + CHECK_PARAM_NOT_EMPTY(pActual); + return true; +} + +#ifdef _WIN32 +extern "C" DLL_EXPORT BOOL CStyle_Array_Object_Out(VARIANT *pActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(pActual); + + ChangeArrayValue(pActual, cActual); + + return true; +} +#endif + +extern "C" DLL_EXPORT BOOL CStyle_Array_Uint_Out(UINT *pActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(pActual); + + ChangeArrayValue(pActual, cActual); + + return true; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Short_Out(SHORT *pActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(pActual); + + ChangeArrayValue(pActual, cActual); + + return true; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Word_Out(WORD *pActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(pActual); + + ChangeArrayValue(pActual, cActual); + + return true; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Long64_Out(LONG64 *pActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(pActual); + + ChangeArrayValue(pActual, cActual); + + return true; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_ULong64_Out(ULONG64 *pActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(pActual); + + ChangeArrayValue(pActual, cActual); + + return true; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Double_Out(DOUBLE *pActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(pActual); + + ChangeArrayValue(pActual, cActual); + + return true; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Float_Out(FLOAT *pActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(pActual); + + ChangeArrayValue(pActual, cActual); + + return true; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Byte_Out(BYTE *pActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(pActual); + + ChangeArrayValue(pActual, cActual); + + return true; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Char_Out(CHAR *pActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(pActual); + + ChangeArrayValue(pActual, cActual); + + return true; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_LPSTR_Out(LPSTR *pActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(pActual); + + ChangeArrayValue(pActual, cActual); + + return true; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Struct_Out(TestStruct *pActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(pActual); + + ChangeArrayValue(pActual, cActual); + + return true; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Bool_Out(BOOL *pActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(pActual); + + for (int i = 0; i < cActual; ++i) + { + if (i % 2 != 0) + pActual[i] = TRUE; + else + pActual[i] = FALSE; + } + + return true; +} + +/////////////////////////////////////////// InAttribute ByRef ///////////////////////////////////////// +extern "C" DLL_EXPORT BOOL CStyle_Array_Int_In_Ref(int **ppActual, int cActual) +{ + if (!CStyle_Array_Int(*ppActual, cActual)) + { + return false; + } + ChangeArrayValue(*ppActual, cActual); + return true; +} + +#ifdef _WIN32 +extern "C" DLL_EXPORT BOOL CStyle_Array_Object_In_Ref(VARIANT **ppActual, int cActual) +{ + if (!CStyle_Array_Object(*ppActual, cActual)) + return false; + + ChangeArrayValue(*ppActual, cActual); + return true; +} +#endif + +extern "C" DLL_EXPORT BOOL CStyle_Array_Uint_In_Ref(UINT **ppActual, int cActual) +{ + if (!CStyle_Array_Uint(*ppActual, cActual)) + return false; + + ChangeArrayValue(*ppActual, cActual); + return true; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Short_In_Ref(SHORT **ppActual, int cActual) +{ + if (!CStyle_Array_Short(*ppActual, cActual)) + return false; + + ChangeArrayValue(*ppActual, cActual); + return true; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Word_In_Ref(WORD **ppActual, int cActual) +{ + if (!CStyle_Array_Word(*ppActual, cActual)) + return false; + + ChangeArrayValue(*ppActual, cActual); + return true; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Long64_In_Ref(LONG64 **ppActual, int cActual) +{ + if (!CStyle_Array_Long64(*ppActual, cActual)) + return false; + + ChangeArrayValue(*ppActual, cActual); + return true; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_ULong64_In_Ref(ULONG64 **ppActual, int cActual) +{ + if (!CStyle_Array_ULong64(*ppActual, cActual)) + return false; + + ChangeArrayValue(*ppActual, cActual); + return true; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Double_In_Ref(DOUBLE **ppActual, int cActual) +{ + if (!CStyle_Array_Double(*ppActual, cActual)) + return false; + + ChangeArrayValue(*ppActual, cActual); + return true; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Float_In_Ref(FLOAT **ppActual, int cActual) +{ + if (!CStyle_Array_Float(*ppActual, cActual)) + return false; + + ChangeArrayValue(*ppActual, cActual); + return true; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Byte_In_Ref(BYTE **ppActual, int cActual) +{ + if (!CStyle_Array_Byte(*ppActual, cActual)) + return false; + + ChangeArrayValue(*ppActual, cActual); + return true; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Char_In_Ref(CHAR **ppActual, int cActual) +{ + if (!CStyle_Array_Char(*ppActual, cActual)) + return false; + + ChangeArrayValue(*ppActual, cActual); + return true; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_LPCSTR_In_Ref(LPCSTR **ppActual, int cActual) +{ + if (!CStyle_Array_LPCSTR(*ppActual, cActual)) + return false; + + ChangeArrayValue(*ppActual, cActual); + return true; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_LPSTR_In_Ref(LPSTR **ppActual, int cActual) +{ + if (!CStyle_Array_LPSTR(*ppActual, cActual)) + return false; + + ChangeArrayValue(*ppActual, cActual); + return true; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Struct_In_Ref(TestStruct **ppActual, int cActual) +{ + if (!CStyle_Array_Struct(*ppActual, cActual)) + return false; + + ChangeArrayValue(*ppActual, cActual); + return true; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Bool_In_Ref(BOOL **ppActual, int cActual) +{ + if (!CStyle_Array_Bool(*ppActual, cActual)) + return false; + + BOOL *pActual = *ppActual; + + for (int i = 0; i < cActual; ++i) + { + if (i % 2 != 0) + pActual[i] = TRUE; + else + pActual[i] = FALSE; + } + + return true; +} + +/////////////////////////////////////////// OutAttribute ByRef ///////////////////////////////////////// +extern "C" DLL_EXPORT BOOL CStyle_Array_Int_Out_Ref(int **ppActual, int cActual) +{ + CHECK_PARAM_EMPTY(*ppActual); + + ChangeArrayValue(*ppActual, cActual); + + return true; +} + +#ifdef _WIN32 +extern "C" DLL_EXPORT BOOL CStyle_Array_Object_Out_Ref(VARIANT **ppActual, int cActual) +{ + CHECK_PARAM_EMPTY(*ppActual); + + ChangeArrayValue(*ppActual, cActual); + + return true; +} +#endif + +extern "C" DLL_EXPORT BOOL CStyle_Array_Uint_Out_Ref(UINT **ppActual, int cActual) +{ + CHECK_PARAM_EMPTY(*ppActual); + + ChangeArrayValue(*ppActual, cActual); + + return true; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Short_Out_Ref(SHORT **ppActual, int cActual) +{ + CHECK_PARAM_EMPTY(*ppActual); + + ChangeArrayValue(*ppActual, cActual); + + return true; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Word_Out_Ref(WORD **ppActual, int cActual) +{ + CHECK_PARAM_EMPTY(*ppActual); + + ChangeArrayValue(*ppActual, cActual); + + return true; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Long64_Out_Ref(LONG64 **ppActual, int cActual) +{ + CHECK_PARAM_EMPTY(*ppActual); + + ChangeArrayValue(*ppActual, cActual); + + return true; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_ULong64_Out_Ref(ULONG64 **ppActual, int cActual) +{ + CHECK_PARAM_EMPTY(*ppActual); + + ChangeArrayValue(*ppActual, cActual); + + return true; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Double_Out_Ref(DOUBLE **ppActual, int cActual) +{ + CHECK_PARAM_EMPTY(*ppActual); + + ChangeArrayValue(*ppActual, cActual); + + return true; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Float_Out_Ref(FLOAT **ppActual, int cActual) +{ + CHECK_PARAM_EMPTY(*ppActual); + + ChangeArrayValue(*ppActual, cActual); + + return true; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Byte_Out_Ref(BYTE **ppActual, int cActual) +{ + CHECK_PARAM_EMPTY(*ppActual); + + ChangeArrayValue(*ppActual, cActual); + + return true; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Char_Out_Ref(CHAR **ppActual, int cActual) +{ + CHECK_PARAM_EMPTY(*ppActual); + + ChangeArrayValue(*ppActual, cActual); + + return true; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_LPCSTR_Out_Ref(LPCSTR **ppActual, int cActual) +{ + CHECK_PARAM_EMPTY(*ppActual); + + ChangeArrayValue(*ppActual, cActual); + + return true; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_LPSTR_Out_Ref(LPSTR **ppActual, int cActual) +{ + CHECK_PARAM_EMPTY(*ppActual); + + ChangeArrayValue(*ppActual, cActual); + + return true; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Struct_Out_Ref(TestStruct **ppActual, int cActual) +{ + CHECK_PARAM_EMPTY(*ppActual); + + ChangeArrayValue(*ppActual, cActual); + + return true; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Bool_Out_Ref(BOOL **ppActual, int cActual) +{ + CHECK_PARAM_EMPTY(*ppActual); + + BOOL *pArray = *ppActual; + for (int i = 0; i < cActual; ++i) + { + if (i % 2 != 0) + pArray[i] = TRUE; + else + pArray[i] = FALSE; + } + + return true; +} + +/////////////////////////////////////////// InAttribute OutAttribute ByRef ///////////////////////////////////////// +extern "C" DLL_EXPORT BOOL CStyle_Array_Int_InOut_Ref(int **ppActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(*ppActual); + + BOOL retval = CStyle_Array_Int_In_Ref(ppActual, cActual); + ChangeArrayValue(*ppActual, cActual); + + return retval; +} + +#ifdef _WIN32 +extern "C" DLL_EXPORT BOOL CStyle_Array_Object_InOut_Ref(VARIANT **ppActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(*ppActual); + + BOOL retval = CStyle_Array_Object_In_Ref(ppActual, cActual); + ChangeArrayValue(*ppActual, cActual); + + return retval; +} +#endif + +extern "C" DLL_EXPORT BOOL CStyle_Array_Uint_InOut_Ref(UINT **ppActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(*ppActual); + + BOOL retval = CStyle_Array_Uint_In_Ref(ppActual, cActual); + ChangeArrayValue(*ppActual, cActual); + + return retval; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Short_InOut_Ref(SHORT **ppActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(*ppActual); + + BOOL retval = CStyle_Array_Short_In_Ref(ppActual, cActual); + ChangeArrayValue(*ppActual, cActual); + + return retval; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Word_InOut_Ref(WORD **ppActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(*ppActual); + + BOOL retval = CStyle_Array_Word_In_Ref(ppActual, cActual); + ChangeArrayValue(*ppActual, cActual); + + return retval; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Long64_InOut_Ref(LONG64 **ppActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(*ppActual); + + BOOL retval = CStyle_Array_Long64_In_Ref(ppActual, cActual); + ChangeArrayValue(*ppActual, cActual); + + return retval; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_ULong64_InOut_Ref(ULONG64 **ppActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(*ppActual); + + BOOL retval = CStyle_Array_ULong64_In_Ref(ppActual, cActual); + ChangeArrayValue(*ppActual, cActual); + + return retval; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Double_InOut_Ref(DOUBLE **ppActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(*ppActual); + + BOOL retval = CStyle_Array_Double_In_Ref(ppActual, cActual); + ChangeArrayValue(*ppActual, cActual); + + return retval; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Float_InOut_Ref(FLOAT **ppActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(*ppActual); + + BOOL retval = CStyle_Array_Float_In_Ref(ppActual, cActual); + ChangeArrayValue(*ppActual, cActual); + + return retval; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Byte_InOut_Ref(BYTE **ppActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(*ppActual); + + BOOL retval = CStyle_Array_Byte_In_Ref(ppActual, cActual); + ChangeArrayValue(*ppActual, cActual); + + return retval; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Char_InOut_Ref(CHAR **ppActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(*ppActual); + + BOOL retval = CStyle_Array_Char_In_Ref(ppActual, cActual); + ChangeArrayValue(*ppActual, cActual); + + return retval; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_LPCSTR_InOut_Ref(LPCSTR **ppActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(*ppActual); + + BOOL retval = CStyle_Array_LPCSTR_In_Ref(ppActual, cActual); + ChangeArrayValue(*ppActual, cActual); + + return retval; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_LPSTR_InOut_Ref(LPSTR **ppActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(*ppActual); + + BOOL retval = CStyle_Array_LPSTR_In_Ref(ppActual, cActual); + ChangeArrayValue(*ppActual, cActual); + + return retval; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Struct_InOut_Ref(TestStruct **ppActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(*ppActual); + + BOOL retval = CStyle_Array_Struct_In_Ref(ppActual, cActual); + ChangeArrayValue(*ppActual, cActual); + + return retval; +} + +extern "C" DLL_EXPORT BOOL CStyle_Array_Bool_InOut_Ref(BOOL **ppActual, int cActual) +{ + CHECK_PARAM_NOT_EMPTY(*ppActual); + + BOOL retval = CStyle_Array_Bool_In_Ref(ppActual, cActual); + + BOOL *pArray = *ppActual; + for (int i = 0; i < cActual; ++i) + { + if (i % 2 != 0) + pArray[i] = TRUE; + else + pArray[i] = FALSE; + } + + return retval; +} + +////////////////////////////////Added marshal array of struct as LPArray////////////////////////////////// +extern "C" DLL_EXPORT BOOL MarshalArrayOfStructAsLPArrayByVal(S2 *pActual, int cActual, S2* pExpect) +{ + bool breturn = true; + S2 *correctArr = pExpect; + if (!(ValidateS2LPArray(pActual, correctArr, cActual))) + { + breturn = false; + } + for (int j = 0; j < cActual; j++) + { + InstanceS2(&pActual[j], 0, 32, 0, 16, 0, 8, 0, 16, 0, 64, 64.0F, 6.4); + } + return breturn; +} + +extern "C" DLL_EXPORT BOOL MarshalArrayOfStructAsLPArrayByRef(S2 **pActual, int cActual, S2* pExpect) +{ + return MarshalArrayOfStructAsLPArrayByVal(*pActual, cActual, pExpect); +} + +extern "C" DLL_EXPORT BOOL MarshalArrayOfStructAsLPArrayByValOut(S2 *pActual, int cActual) +{ + BOOL breturn = true; + for (int j = 0; j < cActual; j++) + { + InstanceS2(&pActual[j], 0, 32, 0, 16, 0, 8, 0, 16, 0, 64, 64.0F, 6.4); + } + return breturn; +} + +extern "C" DLL_EXPORT BOOL MarshalArrayOfStructAsLPArrayByValInOut(S2 *pActual, int cActual) +{ + BOOL breturn = true; + return breturn; +} + +extern "C" DLL_EXPORT BOOL MarshalArrayOfStructAsLPArrayByRefOut(S2 **pActual, int cActual) +{ + BOOL breturn = true; + for (int j = 0; j < cActual; j++) + { + InstanceS2(&((*pActual)[j]), 0, 32, 0, 16, 0, 8, 0, 16, 0, 64, 64.0F, 6.4); + } + return breturn; +} diff --git a/tests/src/Interop/common/types.h b/tests/src/Interop/common/types.h index b4bbcde..26b49ac 100755 --- a/tests/src/Interop/common/types.h +++ b/tests/src/Interop/common/types.h @@ -19,7 +19,7 @@ typedef char* LPSTR; typedef const char* LPCSTR; typedef void* FARPROC; typedef void* HMODULE; -typedef unsigned error_t; +typedef int error_t; typedef void* LPVOID; typedef unsigned char BYTE; typedef WCHAR OLECHAR; -- 2.7.4