I'm playing with C++ interoperability and specifically with C# at the moment. I have a C++ DLL containing a C style API that I want to make available for C# and most of the time I am finding that it is not too bad. However, I am having a terrible time with bool arrays. The below code and output should explain the problem.
The bool array can be passed in, examined and altered, but any changes do not remain in the C# code after returning from the dll. By contrast if you try this with say a double array it works perfectly. You don't even need to use a MarshalAs attribute in the declaration and can pass it as tried below with TestMethod19. I believe the reason is that a bool size on C# is 4 bytes but is 1 byte on C++ (checked with Marshal.SizeOf and sizeof respectively), but what can I do to make this work?
Passing Array of Bool to C++ Code from C# does not appear to be a duplicate. The responses say to Marshal as an I1
, which my tests show doesn't work. I think that question was meant for a bool array in variable that is only meant for reading. However I am also looking for this array to be an out variable.
C++ Declaration .h:
extern "C" DECLSPEC void TestMethod15(bool* d);
C++ Definition .cpp:
void TestMethod15(bool* d)
{
cout << "Inside Test Method 15. ";
cout << "Printing bool array param: ";
for (int i = 0; i < 5; i++)
{
cout << d[i] << ",";
}
cout << endl << "Putting values in the bool array: ";
for (int i = 0; i < 5; i++)
{
d[i] = i % 2 == 0;
cout << d[i] << ",";
}
cout << endl;
}
C# Declarations
public class QuizzerEngine
{
[DllImport("QuizzerEngine.DLL", CallingConvention = CallingConvention.Cdecl)]
public static extern void TestMethod15(
[param: MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.I1)] bool[] bAr);
[DllImport("QuizzerEngine.DLL", CallingConvention = CallingConvention.Cdecl, EntryPoint = "TestMethod15")]
public static extern void TestMethod16(
[param: MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U1)] bool[] bAr);
[DllImport("QuizzerEngine.DLL", CallingConvention = CallingConvention.Cdecl, EntryPoint = "TestMethod15")]
public static extern void TestMethod17(
[param: MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Bool)] bool[] bAr);
[DllImport("QuizzerEngine.DLL", CallingConvention = CallingConvention.Cdecl, EntryPoint = "TestMethod15")]
public static extern void TestMethod18(
[param: MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.VariantBool)] bool[] bAr);
[DllImport("QuizzerEngine.DLL", CallingConvention = CallingConvention.Cdecl, EntryPoint = "TestMethod15")]
public static extern void TestMethod19(
bool[] bAr);
}
C# Calls
{
bool[] boolArray = new bool[5];
boolArray[1] = true;
QuizzerEngine.TestMethod15(boolArray);
Console.WriteLine("After TM15: {0},{1},{2},{3},{4}\n", boolArray[0], boolArray[1], boolArray[2], boolArray[3], boolArray[4]);
}
{
bool[] boolArray = new bool[5];
boolArray[1] = true;
QuizzerEngine.TestMethod16(boolArray);
Console.WriteLine("After TM16: {0},{1},{2},{3},{4}\n", boolArray[0], boolArray[1], boolArray[2], boolArray[3], boolArray[4]);
}
{
bool[] boolArray = new bool[5];
boolArray[1] = true;
QuizzerEngine.TestMethod17(boolArray);
Console.WriteLine("After TM17: {0},{1},{2},{3},{4}\n", boolArray[0], boolArray[1], boolArray[2], boolArray[3], boolArray[4]);
}
{
bool[] boolArray = new bool[5];
boolArray[1] = true;
QuizzerEngine.TestMethod18(boolArray);
Console.WriteLine("After TM18: {0},{1},{2},{3},{4}\n", boolArray[0], boolArray[1], boolArray[2], boolArray[3], boolArray[4]);
}
{
bool[] boolArray = new bool[5];
boolArray[1] = true;
QuizzerEngine.TestMethod18(boolArray);
Console.WriteLine("After TM19: {0},{1},{2},{3},{4}\n", boolArray[0], boolArray[1], boolArray[2], boolArray[3], boolArray[4]);
}
Output:
Inside Test Method 15. Printing bool array param: 0,1,0,0,0,
Putting values in the bool array: 1,0,1,0,1,
After TM15: False,True,False,False,False
Inside Test Method 15. Printing bool array param: 0,1,0,0,0,
Putting values in the bool array: 1,0,1,0,1,
After TM16: False,True,False,False,False
Inside Test Method 15. Printing bool array param: 0,0,0,0,1,
Putting values in the bool array: 1,0,1,0,1,
After TM17: False,True,False,False,False
Inside Test Method 15. Printing bool array param: 0,0,255,255,0,
Putting values in the bool array: 1,0,1,0,1,
After TM18: False,True,False,False,False
Inside Test Method 15. Printing bool array param: 0,0,255,255,0,
Putting values in the bool array: 1,0,1,0,1,
After TM19: False,True,False,False,False