[Mono-dev] Communicating native C structs with managed code

Ivo Smits Ivo at UFO-Net.nl
Sat Jan 6 20:15:53 UTC 2018


Hi Ramin,

You can pass native pointers between C and C# using the IntPtr, void* or 
S1* (where S1 is the struct defined below) in P/Invoke calls. You can 
pass a struct to a P/Invoke using the ref modifier, which will, whenever 
possible, also pass a pointer to the struct. You can pass a native 
pointer from C to a ref parameter in a C# function. To use native 
pointers, you have to mark the affected code block as unsafe. For example:

[StructLayout(LayoutKind.Sequential)]
unsafe struct S1 {
     public double x;
     public double y;
     public Int64 z;
     public fixed int arr[256];
};

The unsafe keyword marks the structure as unsafe - it can only contain 
types which do not need marshalling. StructLayout can be used to specify 
the alignment options, usually the default works. StructLayout.Explicit 
and the FieldOffset attribute can be used to place fields at arbitrary 
offsets, for example to create "unions".

The fixed (int) defines an inline array which behaves like a pointer 
(like it would in C). This array can not be used as a regular array, but 
its members can be accessed using an index. There's no bounds checking.

You can then pass the struct to an external C function using one of the 
following options:
class Test {
       [DllImport("native.so")]
       public static extern void nativemethod1(ref S1 arg);
       [DllImport("native.so")]
       public static extern void nativemethod2(S1* arg);
       [DllImport("native.so")]
       public static extern void nativemethod3(void* arg);
       [DllImport("native.so")]
       public static extern void nativemethod4(IntPtr arg);

     unsafe void Test() {
       S1 s = new S1();
       nativemethod1(ref s);
       nativemethod2(&s); //only works because we're in an unsafe block 
and the struct is marked unsafe
       nativemethod3(&s);
       nativemethod4((IntPtr)(&s));
     }
}

The other way around works as well, for example:
class Test {
       [DllImport("native.so")]
       public static extern S1* nativemethod1();
       [DllImport("native.so")]
       public static extern IntPtr nativemethod3();

     unsafe void Test() {
       S1* s = nativemethod1();
       s = (S1*)nativemethod3(); //cast if you used an IntPtr
       s->x = 6; //the structure can now be modified directly. Make sure 
it's not released in the native code...
     }
}

--
Ivo


Op 5-1-2018 om 10:59 schreef R Zaghi:
> Hi
>
> What would be the most performance efficient method to pass a native C 
> struct of primitive data types (memory aligned or compact) to the 
> managed code in Mono/C# and allow modification of its member variables 
> in the managed code?
>
> Do we have anything specific in Mono that helps eliminate manual 
> marshalling on every call? or could we? :)
>
> Say, in the following scenarios:
>
> struct S1 {
> double x,
> double y,
> double z
> };
>
> Or
>
> struct S2 {
> int arr[256]
> };
>
> Or
>
> struct S3 {
> double x,
> int arr[256]
> };
>
>
>
> Ramin
>
>
>
> -- 
>
>
>
> Ramin Zaghi
>
> *Mosaic3DX™ | User Interface Technology*
> St John's Innovation Centre,
> Cowley Road,
> Cambridge,
> CB4 0WS, UK*
> *
> *E*:**rzaghi at mosaic3dx.com <mailto:rzaghi at mosaic3dx.com>
> *T*: +44 1223 421 311
> http://linkedin.com/in/raminzaghi
>
>
>
> _______________________________________________
> Mono-devel-list mailing list
> Mono-devel-list at lists.dot.net
> http://lists.dot.net/mailman/listinfo/mono-devel-list

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.dot.net/pipermail/mono-devel-list/attachments/20180106/6ecc65a3/attachment.html>


More information about the Mono-devel-list mailing list