Marshal bool array to dll

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
 
N

Nicholas Paldino [.NET/C# MVP]

gpg,

Can you show the original structure declaration in C?
 
G

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 );
 
M

Mattias Sjögren

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
 
G

gpg

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

Top