Passing an array of structs to a DLL via P/Invoke

EDN Admin

Well-known member
Joined
Aug 7, 2010
Messages
12,794
Location
In the Machine
I have a non-COM DLL that Im trying to use in a C# app Im working on. The DLL is a database management API. My problem is with the DLL function that creates a table. Theres a struct that describes one column, and the function expects
an array of this struct to describe the table. Its a 3rd party DLL, but although I have the source code, I cant modify it. The DLL is implemented in unmanaged C.
The relevant DLL code looks like this:

<div style="color:Black;background-color:White; <pre>
<span style="color:Blue; typedef <span style="color:Blue; struct
{
<span style="color:Blue; char *name ;
<span style="color:Blue; short <span style="color:Blue; int type;
<span style="color:Blue; unsigned <span style="color:Blue; short <span style="color:Blue; int len;
<span style="color:Blue; unsigned <span style="color:Blue; short <span style="color:Blue; int dec;
<span style="color:Blue; unsigned <span style="color:Blue; short <span style="color:Blue; int nulls; <span style="color:Green; /* are nulls allowed? */
} COLUMN;

<span style="color:Blue; int create(<span style="color:Blue; int handle, <span style="color:Blue; const <span style="color:Blue; char* path, <span style="color:Blue; const COLUMN[] cols)
{
<snip>
<span style="color:Blue; for (<span style="color:Blue; int i=0; cols.name; i++)
{
<span style="color:Green; // Calculate table layout, etc......
}
<snip>
}
[/code]

You can see that its supposed to continue adding columns until the name field in a struct is null. The calling code is expected to include a zero-filled struct as the final element in the column definition array. So, I declared the following
in my C# code:

<div style="color:Black;background-color:White; <pre>
[StructLayout(LayoutKind.Sequential)]
<span style="color:Blue; public <span style="color:Blue; struct COLUMN
{
[MarshalAs(UnmanagedType.LPStr)]
<span style="color:Blue; public <span style="color:Blue; string name;
<span style="color:Blue; public <span style="color:Blue; int type;
<span style="color:Blue; public <span style="color:Blue; int length;
<span style="color:Blue; public <span style="color:Blue; int decimals;
<span style="color:Blue; public <span style="color:Blue; int nulls;
}

[DllImport(<span style="color:#A31515; "c4dll.dll")]
<span style="color:Blue; static <span style="color:Blue; extern <span style="color:Blue; int d4create([MarshalAs(UnmanagedType.LPStr)] <span style="color:Blue; string path, [MarshalAs(UnmanagedType.LPArray)] COLUMN[] cols);

[/code]

and call it like this:

<div style="color:Black;background-color:White; <pre>
COLUMN[] cols = <span style="color:Blue; new COLUMN[3];

cols[0].name = <span style="color:#A31515; "Id";
cols[0].type = <span style="color:#A31515; I; <span style="color:Green; // integer
cols[0].length = 4;
cols[0].decimalPlaces = 0;
cols[0].allowNulls = 0;
cols[1].name = <span style="color:#A31515; "Name";
cols[1].type = <span style="color:#A31515; C; <span style="color:Green; // text
cols[1].length = 65;
cols[1].decimalPlaces = 0;
cols[1].allowNulls = 0;

<span style="color:Blue; int status = create(<span style="color:#A31515; "C:\test\Table1", cols);
[/code]
The function returns a code indicating success, and the table is created, but it only contains a single column. I can see in the debugger just prior to calling create() that the data in the array is correct, including the final null struct.

Ive searched both MSDN and other places for help, but it seems other people are trying to pass emtpy arrays to the DLL (expecting the DLL to populate them). Solutions from those posts dont work for me. Its like only the first struct in the
array is getting passed to the DLL. What am I missing?

View the full article
 
Back
Top