How to marshal structure containing variable length array?
Have you ever run into situation where you have to call into a classic C DLL
that returns you an opaque pointer (
VOID) that contains a
structure containing an array of variable length? For example look at the
following structures defined in header file of unmanaged C DLL.
typedef struct _MY_DATA
typedef struct _MY_CCONTAINER
Second structure MY_CONTAINER has an opaque member hContainingData
and this member represents the first structure MY_DATA. The trouble part
is usValues member in MY_DATA structure. This is defined as an
array of dimension one. The actual size of this array is determined by member uiSize.
Now the question is how do we define this structure prototype in our .Net
application. If the array was of fixed size then it was easy and we could have
defined it the following way (assuming that size of array is 10).
public UInt16 usData;
public UInt32 uiSize;
public UInt16  usValues;
Unfortunately we can't define protype like this for an embded array whose size
will be known at run time. And .Net framework does not provide any support for
these kind of embded arrays. There are few possible solutions for this problem.
One could be that you define the prototype assuming the array is of very large
size and then at run time
uiSize memeber will be used to determine
the exact size of array and access the array for those number of elements. The
problem with this approach is that it is not possible to pre-detemine size of
array. If you assign a very large number, you will end up reserving a lot of
memory which will be unused. And then you have to rely on the callee function
that it will not try to assign memory beyond the allocated size.
I will demonstrate an approach that does not require you to pre-define the size
of array. This approach involves manually walking the memory block returned by
unmanaged function, and accessing every variable individually. This apprach
requires help from a few Win32 functions that we will call using PInvoke.
First we take a look at the unamanged function protype.
BOOL OutStructWithArray(LPVOID inoutStruct);
.Net protype definition for this function will be as follows.
internal class MY_CONTAINER
internal ushort usType;
internal IntPtr hContainerData;
internal static extern bool OutStructWithArray([In, Out]MY_CONTAINER obMyCont);
Following code snippet demonstrates how each member of the array is accsses by
manually walking the memory location returned by unmanaged code.
static void Main(string args)
MY_CONTAINER obMyCont = new MY_CONTAINER();
obMyCont.usType = 12;
obMyCont.hContainerData = IntPtr.Zero;
bool bRet = StructsTest.OutStructWithArray(obMyCont);
if (bRet && obMyCont.hContainerData != IntPtr.Zero)
// Lock the memory block.
IntPtr pData = StructsTest.GlobalLock(obMyCont.hContainerData);
IntPtr pArrayLocation = pData;
// Read usData1 values.
UInt16 uiData1 = (UInt16)Marshal.ReadInt16(pData);
// Read size of the array at offset of uiType memeber variable.
int iOffset = Marshal.SizeOf(Type.GetType("System.UInt16"));
Int32 uiSize = Marshal.ReadInt32(pData, iOffset);
// Allocate buffer to get copy of the array.
Int16  vals = new Int16[uiSize];
// Advance to the location of the array.
iOffset += Marshal.SizeOf(Type.GetType("System.UInt32"));
pArrayLocation = (IntPtr)((int)pArrayLocation + iOffset);
Marshal.Copy(pArrayLocation, vals, 0, uiSize);
The attached soource code contains the unmanaged as well as managed projects
that demonstrate this approach.