[Mono-list] Re: Marshaling unmanaged structure

Robert Jordan robertj at gmx.net
Wed Aug 31 04:32:11 EDT 2005


Hi Javier,

> Ok, I understand :)
> 
> Another question, how should I get access to the nested structures?,
> some unmanaged functions need access to the structures..

first declare a dummy field for the struct begining with
the first offset of the union:

    [StructLayout (LayoutKind.Explicit)]
    public struct event_struct {
  		[FieldOffset(0)] public IntPtr next;
  		[FieldOffset(4)] public int type;
  		[FieldOffset(8)] public int unionStart;
                 ....

With Marshal.OffsetOf (typeof (event_struct), "unionStart")
you get the offset of the start of the union within the struct.

Next you have to change all p/invoke declarations to take
an IntPtr as an argument instead of the struct name:

from

	static extern int foo (ev_levels input, ev_levels output);

to
	static extern int foo (IntPtr input, IntPtr output);

Before you call such a p/invoke method you have to pin the
struct, because the default marshal cannot help you anymore:

int managed_foo (event_struct input , event_struct output)
{
   GCHandle h1 = GCHandle.Alloc (input, GCHandleType.Pinned);
   GCHandle h2 = GCHandle.Alloc (output, GCHandleType.Pinned);
   try {
     // this is actually a constant, you may factor the call out.
     IntPtr offset = Marshal.OffsetOf (typeof (event_struct),
                                       "unionStart");
     return levels_callback (h1.AddrOfPinnedObject () + offset,
                             h2.AddrOfPinnedObject () + offset);
   }
   finally {
     h1.Free ();
     h2.Free ();
   }
}


onother way (which I never used with Mono) using "unsafe" code
and pointers:

unsafe int managed_foo (event_struct input , event_struct output)
{
   fixed (int* i = &input.ev.input)
   fixed (int* o = &output.ev.output) {
     return levels_callback (new IntPtr(i), new IntPtr(o));
   }
}


> ---------------------------------------
>
> can I create something like this ?
>
> ---------------------------------------
> public struct new_event_struct : event_struct {
> 	public ev_levels levels {
> 		get { return ....; }
> 	}
> }
> ---------------------------------------

I don't know. You must use classes for inheritance. I don't know
how classes and inheritance cope with FieldOffset and StructLayout.

Rob



More information about the Mono-list mailing list