I've got an unmanaged DLL that I am trying to use that makes use of some nested structs with reserved members at the end of them. I'm having an issue converting them to C#.
I've tried to strip down the code to what is essential. The ParentStruct has members for four instances of three different child structs. All of those three different child structs have void* arrays to reserve memory for future use.
I've tried just doing the Reserved values as IntPtrs, I've tried turning on unsafe code and using the fixed keyword (and changing them to ints). I've tried actually laying out the appropriate number of consecutive IntPtrs at the end of the struct. Nothing seems to work.
In some of those cases, I'll get an error message (an uninformative one that says that there was an error at a certain address on a certain thread). Most of the time, though, the application just dies without an error message. I'm sure that's because I'm messing with unmanaged memory here.
Just FYI, the actual Pinvoke has a signature something like
[DllImport("MyDll.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
internal static extern void UseStructs([In,Out] ref ParentStruct parent);
So what's the right way to declare these structs in C# so that I can use them?
typedef struct
{
ChildStruct1 childOne;
ChildStruct2 childTwo;
ChildStruct2 childTwoB;
ChildStruct3 childThree;
#if defined K_64_BIT
/// Reserved for future implementation
void* Reserved[15];
#elif defined K_32_BIT
/// Reserved for future implementation
void* Reserved[14];
#endif
} ParentStruct;
typedef struct
{
bool Valid;
float x;
float y;
/// Reserved for future implementation.
void* Reserved[16];
} ChildStruct3;
typedef struct
{
bool Found;
XYPairFloat xyPair;
/// Reserved for future implementation.
void* Reserved[16];
} ChildStruct2;
typedef struct
{
unsigned char* imageData;
RectInt rectInt;
#if defined QUICK_LINK_64_BIT
/// Reserved for future implementation
void* Reserved[14];
#elif defined QUICK_LINK_32_BIT
/// Reserved for future implementation
void* Reserved[12];
#endif
} ChildStruct1;
typedef struct
{
int x;
int y;
int width;
int height;
} RectInt;
typedef struct
{
float x;
float y;
} XYPairFloat;
Edit: I think I've gotten closer, in that I'm now getting an error message that is at least human readable. But it still doesn't work. I used the fixed keyword on the Reserved members and set the SizeConst part of the attribute on the member appropriately. Everything else I did was just basic pinvoke work. However, I'm getting the error:
The type definition of this field has layout information but has an invalid managed/unmanaged type combination or is unmarshalable.
in reference to the ChildStruct1 childOne member, which is the first one so I'd venture a guess it applies to the others as well. Thoughts?
Edit 2: Per Mark Heath's request, here's the actual definition I'm using for ChildStruct1:
[StructLayout(LayoutKind.Sequential)]
internal unsafe struct ChildStruct1
{
[MarshalAs(UnmanagedType.LPStr)]
public string imageData;
public RectInt rectInt;
[MarshalAs(UnmanagedType.LPArray, SizeConst=12)]
public fixed int Reserved[12];
}
Edit 3: I did a little more digging. That error that I'm getting disappears if I comment out the Reserved member. Obviously it doesn't work. But that particular error is caused by how I defined that member, I guess.