PInvoke and structs question question

  • Thread starter =?ISO-8859-1?Q?Carlos_Guzm=E1n_=C1lvarez?=
  • 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
 
T

Tom Shelton

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).
 
?

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

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.
 
M

Mattias Sjögren

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
 
?

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

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.
 
?

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

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.
 

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