Toby999
Toby999

Reputation: 604

How do you get data back from C in a C# instantiated array in an C# interop call?

I would like to instantiate memory for a boolean array in C# and pass this to a C library function using interop. Then the C function should fill up the array with data (result) so that the data can passed back to C# and used there. Since arrays are reference types and since I explicitly set the [In, Out] marshalling attribute for the array I thought this would be a piece of cake. But apparantly not. :-( Below is some test code (as simple as I could get it) that illuminates the problem.

In C, here is what I will call:

extern "C" __declspec(dllexport) int __stdcall TestFillArray(bool *resultMaterials, int materialLength);


__declspec(dllexport) int __stdcall TestFillArray(bool *resultMaterials, int materialLength)
{
    resultMaterials[0] = true; 
    resultMaterials[1] = true; 
    return materialLength;
}

I call this function from C# using the following declaration:

[DllImport("FrontAuction2.dll", CharSet = CharSet.Auto, SetLastError = true, CallingConvention = CallingConvention.StdCall)]
public static extern int TestFillArray([MarshalAs(UnmanagedType.LPArray, SizeConst = 2), In, Out] bool[] resultMaterial, int materialLength);

then within my C# test method I have:

var resultMaterials = new bool[2];
var res = TestFillArray(resultMaterials, 2);

When I check the result, I get res=2 and resultMaterials[0] = true, and resultMaterials[1] = false. I.e. the res value is correct as well as the first array element´, but not the second one. So it seems that the boolean data is not marshalled correctly (unless I am missing something obvious).

I am guessing it also would be possible to declare a IntPtr instead of an array and succesfully marshal the two elements to the correct result. However, since I want the array to be allocated in memory in C#, I am not sure how to do this.

Much obliged for help on this. I'm kind of stuck here. :(


UPDATE: I am guessing that it is due to that boolean is only 1 byte long and that the C# code does not get this information. So how do you specify this?

Upvotes: 2

Views: 204

Answers (1)

svick
svick

Reputation: 244908

Using

[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.I1, SizeConst = 2), In, Out]

should tell the framework to mashal the array as an array of 1-byte bools. Another option would be to use the 4-byte BOOL instead. For more information see UnmanagedType enum.

Upvotes: 1

Related Questions