Marshal bool array to dll

  • Thread starter Thread starter gpg
  • Start date Start date
G

gpg

I am using a legacy DLL and need to marshal some structures for use in
the DLL. For the most part, I have figured out my needs except for one
small item.

I have a structure that contain, among other items, an array of bools
(not BOOL). The array is a fixed size and is contained in the
structure.

Should be simple ie:

[StructLayout(LayoutKind.Sequential)]
public struct MyArrayStruct2
{
[MarshalAs(UnmanagedType.I1)]
public bool flag;
[MarshalAs(UnmanagedType.I1)]
public bool flag2;
public int val1;
public int val2;
[MarshalAs(UnmanagedType.ByValArray, ArraySubType =
UnmanagedType.I1, SizeConst = 9)]
public bool[] bArray;
public BoolArray bArray;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public int[] vals;
}

except when the structure is passed to the DLL, the data after the bool
array is broken and the data. I have found this same issue when the
data alignment in the passed structure is incorrect (ie single bool
type passed without the MarshalAs).

I have found a solution, which involves creating another strucure of
only bool (marshalled) and using the reference to this structure in my
main structure.

[StructLayout(LayoutKind.Sequential)]
public struct MyArrayStruct2
{
[MarshalAs(UnmanagedType.I1)]
public bool flag;
[MarshalAs(UnmanagedType.I1)]
public bool flag2;
public int val1;
public int val2;
public BoolArray bArray;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public int[] vals;
}

[StructLayout(LayoutKind.Sequential)]
public struct BoolArray
{
[MarshalAs(UnmanagedType.I1)]
public bool b1;
[MarshalAs(UnmanagedType.I1)]
public bool b2;
// more of the same
[MarshalAs(UnmanagedType.I1)]
public bool b9;
}

This works fine but is ugly and a bit unwieldy. I have tried different
size and packing attributes for the StructLayout to no avail.

Any ideas? It seems that the ByValArray with the subtype of I1 should
work fine.

Thanks!

GPG
 
Here it is along with the function call.

typedef struct _MYARRAYSTRUCT2
{
bool flag;
bool flag2;
long val1;
long val2;
bool bFrequencies[9];
int vals[ 3 ];
} MYARRAYSTRUCT2;

extern "C" PINVOKELIB_API void TestArrayInStruct2( MYARRAYSTRUCT2*
pStruct );
 
Any ideas? It seems that the ByValArray with the subtype of I1 should
work fine.

Indeed, but if you can't get it to work, you can try using a byte[]
instead.


Mattias
 
Well ... I have come up with a "sort of" solution to this issue
although I am of the general consesus that this issue is reflective of
a bug of some sort.

On the C# side I have done the following:

public struct MyArrayStruct2
{
[MarshalAs(UnmanagedType.I1)]
public bool flag;
[MarshalAs(UnmanagedType.I1)]
public bool flag2;
public int val1;
public int val2;
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.I1,
SizeConst = 9)]
public byte[] bArray;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public int[] vals;
}

Notice the change from bool[] to byte[]. Now the consumer initializes
the "bool" array as

myStruct2.bArray = new byte[9];
for (int i = 0; i < 9; i++)
{
myStruct2.bArray = Convert.ToByte(false);
}

and we can conversely read the values from the array as

bool bFlag = Convert.ToBoolean(myStruct2.bArray);

This works with the legacy DLL and everything is happy --- but this is
certainly an awkward and hacky way to perform this.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Back
Top