PInvoke and structs question question

  • Thread starter Thread starter =?ISO-8859-1?Q?Carlos_Guzm=E1n_=C1lvarez?=
  • Start date Start date
?

=?ISO-8859-1?Q?Carlos_Guzm=E1n_=C1lvarez?=

Hello:

I'm trying to execute a function of a unmanaged dll using PInvoke, i
have definied the function as:

[DllImport(FbClient.DllPath)]
public static extern int isc_dsql_prepare(
int[] status_vector,
ref int trans_handle,
ref int stmt_handle,
short length,
string statement,
short dialect,
ref XSQLDA xsqlda);

the XSQLDA structure is defined as:

[StructLayout(LayoutKind.Sequential)]
public struct XSQLDA
{
public short version;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=8)]
public string sqldaid;
public int sqldabc;
public short sqln;
public short sqld;
public XSQLVAR[] sqlvar;
}

[StructLayout(LayoutKind.Sequential)]
public struct XSQLVAR
{
public short sqlType;
public short sqlScale;
public short sqlSubType;
public short sqlLen;
public byte[] sqlData;
public short sqlInd;
public short sqlNameLength;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)]
public string sqlName;
public short relNameLength;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)]
public string relName;
public short ownerNameLength;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)]
public string ownerName;
public short aliasNameLength;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)]
public string aliasName;
}

But i get always a TypeLoadException when i exec it, the problem seems
to be with :

public XSQLVAR[] sqlvar;

Removing this line i can execute the function but i need it :)

Any idea on how to solve this ??



Thanks in advance
 
public XSQLVAR[] sqlvar;

The marshaller does not support arrays of structs inside of structs.
You will want to change this to an IntPtr - since it is a dynmaic sized
array. Then use the members of the marshal class (specifically, I would
look at the Marshal.PtrToStructure and Marshal.SizeOf).
 
Hello:
The marshaller does not support arrays of structs inside of structs.
You will want to change this to an IntPtr - since it is a dynmaic sized
array. Then use the members of the marshal class (specifically, I would
look at the Marshal.PtrToStructure and Marshal.SizeOf).

Thanks, i'm starting to see PInvoke with C# and have a lot of doubts on
how it works :)

One question, i get the same error if i define it as:

public XSQLVAR sqlvar;

It's not supported too ??

And another question, i'm trying to use it with IntPtr as you suggested,
to initialize the IntPtr i'm making:

XSQLDA xsqlda = new XSQLDA();
xsqlda.version = 1;
xsqlda.sqln = 1;
xsqlda.sqlvar = new XSQLVAR[1];
xsqlda.sqlvar[0].sqlData = new byte[0];

int size = Marshal.SizeOf(xsqlda);
IntPtr sqlda = Marshal.AllocCoTaskMem(size);
Marshal.StructureToPtr(xsqlda, sqlda, true);

But i get an ArgumentException on:

int size = Marshal.SizeOf(xsqlda);


Any idea on how to solve it ??


Thanks in advance.
 
Carlos,
But i get an ArgumentException on:

What does the exception message say? I'm guessing it's caused by the
byte[] in XSQLVAR. If it's supposed to be a fixed length array, you
must use the MarshalAs attribute to indicate its size. If it's a
pointer to a variable length array, change its type to an IntPtr or
byte*.



Mattias
 
Hello:
What does the exception message say? I'm guessing it's caused by the
byte[] in XSQLVAR.

You are right :)
If it's supposed to be a fixed length array, you
must use the MarshalAs attribute to indicate its size. If it's a
pointer to a variable length array, change its type to an IntPtr or
byte*.

it's dynamic array, for give a little more or information, the original
C structs are:

typedef struct
{
short sqltype;
short sqlscale;
short sqlsubtype;
short sqllen;
char * sqldata;
short * sqlind;
short sqlname_length;
char sqlname[32];
short relname_length;
char relname[32];
short ownname_length;
char ownname[32];
short aliasname_length;
char aliasname[32];
} XSQLVAR;

typedef struct
{
short version;
char sqldaid[8];
ISC_LONG sqldabc;
short sqln;
short sqld;
XSQLVAR sqlvar[1];
} XSQLDA;


And the original C function definition is:

ISC_STATUS isc_dsql_describe(
ISC_STATUS *status_vector,
isc_stmt_handle *stmt_handle,
unsigned short da_version,
XSQLDA *xsqlda);

And a little sample of use:

ISC_STATUS status_vector[20];
XSQLDA *osqlda;

....

osqlda = (XSQLDA *)malloc(XSQLDA_LENGTH(n);
osqlda->sqln = n;
osqlda->version = SQLDA_VERSION1;
isc_dsql_describe(
status_vector,
&stmt_handle,
1,
osqlda);

....


Can be this handled using PInvoke ??


The C# PInvoke definition i have now is:

[DllImport(FbClient.DllPath)]
public static extern int isc_dsql_describe(
int[] status_vector,
ref int stmt_handle,
short da_version,
ref XSQLDA xsqlda);

And the C# structures i'm using now are:

[StructLayout(LayoutKind.Sequential)]
public struct XSQLVAR
{
public short sqlType;
public short sqlScale;
public short sqlSubType;
public short sqlLen;
public IntPtr sqlData;
public IntPtr sqlInd;
public short sqlNameLength;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)]
public string sqlName;
public short relNameLength;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)]
public string relName;
public short ownerNameLength;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)]
public string ownerName;
public short aliasNameLength;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)]
public string aliasName;
}

[StructLayout(LayoutKind.Sequential)]
public struct XSQLDA : IDisposable
{
public short version;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=8)]
public string sqldaid;
public int sqldabc;
public short sqln;
public short sqld;
public IntPtr sqlvar;
}


Can be this correct for work with PInvoke or not ??



Thanks in advance.
 
Hello:
The marshaller does not support arrays of structs inside of structs.
You will want to change this to an IntPtr - since it is a dynmaic sized
array. Then use the members of the marshal class (specifically, I would
look at the Marshal.PtrToStructure and Marshal.SizeOf).

I think i have it working now, i need to more serious tests using
different functions that make use of these structures, but at least the
first tests seems to be working, thanks very much to all.
 
Back
Top