passing array of structures from C dll to C#

D

dogalacar

Hi All,

I am trying to pass array of structures from a C dll to C# as msdn
sample does(outarrayofstructs sample) but PtrToStructure function gives
error :
--> "structure must not be a value class"

What i am doing wrong ?
here is the code

c code:

typedef struct st2
{
long tt;
} st3;

long ornekfonk(st3 **str)
{
*str = (st3*)CoTaskMemAlloc( 3 * sizeof( st3 ));
(*str)[0].tt = 9;
(*str)[1].tt = 10;
(*str)[2].tt = 11;

return 1;
}

c# code:

[ StructLayout( LayoutKind.Sequential , CharSet=CharSet.Ansi)]
public struct str1
{
public int tt;
}

[DllImport(@"C:\WINDOWS\system32\MapiDll.dll")]
public static extern int ornekfonk( ref IntPtr ptr);

str = new str1();
IntPtr ptr=(IntPtr)0;
ornekfonk(ref ptr);
Marshal.PtrToStructure( ptr, str ); //it gives error here


Thanks in advance
Dogal Acar
 
W

Willy Denoyette [MVP]

Hi All,

I am trying to pass array of structures from a C dll to C# as msdn
sample does(outarrayofstructs sample) but PtrToStructure function gives
error :
--> "structure must not be a value class"

What i am doing wrong ?
here is the code

c code:

typedef struct st2
{
long tt;
} st3;

long ornekfonk(st3 **str)
{
*str = (st3*)CoTaskMemAlloc( 3 * sizeof( st3 ));
(*str)[0].tt = 9;
(*str)[1].tt = 10;
(*str)[2].tt = 11;

return 1;
}

c# code:

[ StructLayout( LayoutKind.Sequential , CharSet=CharSet.Ansi)]
public struct str1
{
public int tt;
}

[DllImport(@"C:\WINDOWS\system32\MapiDll.dll")]
public static extern int ornekfonk( ref IntPtr ptr);

str = new str1();
IntPtr ptr=(IntPtr)0;
ornekfonk(ref ptr);
Marshal.PtrToStructure( ptr, str ); //it gives error here


Thanks in advance
Dogal Acar

Should be...

IntPtr ptr=IntPtr.Zero;
ornekfonk(ref ptr);
str1 str = (str1)Marshal.PtrToStructure(ptr, typeof(str1));

but honestly I don't see how you gonna use this, you have no idea about the
number of struct allocated by the callee.
Note also that you need to free the memory allocated by CoTaskMemAlloc...


Willy.
 
N

Nicholas Paldino [.NET/C# MVP]

Dogal,

I don't think you want to do it this way, as there are a number of
problems.

The first is the declaration of the method. You are declaring the
parameter str as st3**, which is a pointer to a pointer (or in your desired
case, a pointer to an array). While this is not incorrect, the problem here
is that you are doing the assignment of memory in your method, and not
unassigning the memory after it is called (this is a bad practice in
general).

A better alternative would be to have a method which takes a pointer to
the memory location, as well the size of the location, and a parameter for
number of elements written. Something like this:

long ornekfonk /* what the hell is that */(st3 *str, DWORD size, DWORD
*written)
{
// Check the size, if the number of elements is not enough, then set the
*written parameter
// To the size needed, and then return an error code indicating not
enough memory
// was allocated. Otherwise, write to str.
}

Now, the problem with this is that the P/Invoke layer in .NET can't
marshal arrays back from unmanaged code (at least, C-style arrays). The
reason for this is that it doesn't know the size of the array, so it only
marshals back the first element.

To get around this, you have to declare your function the way you did,
passing an IntPtr in (but not by ref). However, before the call, you would
make a call to the static AllocCoTaskMem method on the Marshal class to
allocate the appropriate memory for the array of structures. Upon return,
you have to cycle for the number of elements in the array, adjusting the
IntPtr by the index of the array element you want to read, and then call the
static PtrToStructure method to return the structure at that element.

Hope this helps.
 
P

PW

long ornekfonk /* what the hell is that */(st3 *str, DWORD size, DWORD

This made my day.
 

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