Re: Communicating native C structs with managed code
Ivo Smits <[email protected]> Sat, 6 Jan 2018 21:15:53 +0100
| Newsgroups | gmane.comp.gnome.mono.devel |
|---|---|
| Message-ID | <[email protected]> |
This is a multi-part message in MIME format.
--===============1715578260771353598==
Content-Type: multipart/alternative;
boundary="------------FB5D0FE3265B8DB38C421570"
Content-Language: en-US
This is a multi-part message in MIME format.
--------------FB5D0FE3265B8DB38C421570
Content-Type: text/plain; charset=utf-8; format=flowed
Content-Transfer-Encoding: 8bit
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*:**[email protected] <mailto:[email protected]>
> *T*: +44 1223 421 311
> http://linkedin.com/in/raminzaghi
>
>
>
> _______________________________________________
> Mono-devel-list mailing list
> [email protected]
> http://lists.dot.net/mailman/listinfo/mono-devel-list
--------------FB5D0FE3265B8DB38C421570
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: 8bit
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body text="#000000" bgcolor="#FFFFFF">
<p>Hi Ramin,</p>
<p>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:</p>
<div dir="auto">[StructLayout(LayoutKind.Sequential)]<br>
unsafe struct S1 {</div>
<div dir="auto"> public double x;</div>
<div dir="auto"> public double y;<br>
public Int64 z;<br>
</div>
<div dir="auto"> public fixed int arr[256];</div>
<div dir="auto">};<br>
<br>
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".<br>
<br>
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.<br>
<br>
You can then pass the struct to an external C function using one
of the following options:<br>
class Test {<br>
[DllImport("native.so")]<br>
public static extern void nativemethod1(ref S1 arg);<br>
[DllImport("native.so")]<br>
public static extern void nativemethod2(S1* arg);<br>
</div>
[DllImport("native.so")]<br>
public static extern void nativemethod3(void* arg);<br>
[DllImport("native.so")]<br>
public static extern void nativemethod4(IntPtr arg);<br>
<br>
unsafe void Test() {<br>
S1 s = new S1();<br>
nativemethod1(ref s);<br>
nativemethod2(&s); //only works because we're in an unsafe
block and the struct is marked unsafe<br>
nativemethod3(&s);<br>
nativemethod4((IntPtr)(&s));<br>
}<br>
}<br>
<br>
The other way around works as well, for example:<br>
class Test {<br>
[DllImport("native.so")]<br>
public static extern S1* nativemethod1();<br>
[DllImport("native.so")]<br>
public static extern IntPtr nativemethod3();<br>
<br>
unsafe void Test() {<br>
S1* s = nativemethod1();<br>
s = (S1*)nativemethod3(); //cast if you used an IntPtr<br>
s->x = 6; //the structure can now be modified directly.
Make sure it's not released in the native code...<br>
}<br>
}<br>
<br>
--<br>
Ivo<br>
<br>
<br>
<div class="moz-cite-prefix">Op 5-1-2018 om 10:59 schreef R Zaghi:<br>
</div>
<blockquote type="cite"
cite="mid:CAFLMc5u572Co+7=z_wN8bR=iwx8mZTSwwWYokhWCeezZoAWRzg@mail.gmail.com">
<div dir="auto">Hi</div>
<div dir="auto"><br>
</div>
<div dir="auto">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?</div>
<div dir="auto"><br>
</div>
<div dir="auto">Do we have anything specific in Mono that helps
eliminate manual marshalling on every call? or could we? :)</div>
<div dir="auto"><br>
</div>
<div dir="auto">Say, in the following scenarios:</div>
<div dir="auto"><br>
</div>
<div dir="auto">struct S1 {</div>
<div dir="auto">double x,</div>
<div dir="auto">double y,</div>
<div dir="auto">double z</div>
<div dir="auto">};</div>
<div dir="auto"><br>
</div>
<div dir="auto">Or</div>
<div dir="auto"><br>
</div>
<div dir="auto">struct S2 {</div>
<div dir="auto">int arr[256]</div>
<div dir="auto">};</div>
<div dir="auto"><br>
</div>
<div dir="auto">Or</div>
<div dir="auto"><br>
</div>
<div dir="auto">struct S3 {</div>
<div dir="auto">double x,</div>
<div dir="auto">int arr[256]</div>
<div dir="auto">};</div>
<div dir="auto"><br>
</div>
<div dir="auto"><br>
</div>
<div dir="auto"><br>
</div>
<div dir="auto">Ramin</div>
<div dir="auto"><br>
</div>
<div dir="auto"><br>
</div>
<div dir="auto"><br>
</div>
<div dir="ltr">-- <br>
</div>
<div class="gmail_signature" data-smartmail="gmail_signature">
<div dir="ltr">
<div>
<div dir="ltr">
<div>
<div dir="ltr">
<div>
<div dir="ltr">
<div>
<div dir="ltr"><br>
</div>
<div dir="ltr"><br>
</div>
<div dir="ltr"><br>
</div>
<div dir="ltr">Ramin Zaghi</div>
<div dir="ltr"><br>
<div><img
src="https://drive.google.com/uc?id=0B3xiwa7kf1uwRlYxenBFM1o2NEk&export=download"
moz-do-not-send="true"><b>Mosaic3DX™ | <font
size="1">User Interface Technology</font></b></div>
<div>
<div style="font-size:small">St John's
Innovation Centre,</div>
<div style="font-size:small">Cowley Road,</div>
<div style="font-size:small">Cambridge,</div>
<div style="font-size:small">CB4 0WS, UK<b><br>
</b></div>
<div style="font-size:small"><b>E</b>:<b> </b><a
href="mailto:[email protected]"
target="_blank" moz-do-not-send="true">[email protected]</a></div>
<div style="font-size:small"><b>T</b>: +44
1223 421 311</div>
</div>
<div><font size="2"><a
href="http://linkedin.com/in/raminzaghi"
target="_blank" moz-do-not-send="true">http://linkedin.com/in/raminzaghi</a></font></div>
<div><font size="2"><br>
</font></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<br>
<fieldset class="mimeAttachmentHeader"></fieldset>
<br>
<pre wrap="">_______________________________________________
Mono-devel-list mailing list
<a class="moz-txt-link-abbreviated" href="mailto:[email protected]">[email protected]</a>
<a class="moz-txt-link-freetext" href="http://lists.dot.net/mailman/listinfo/mono-devel-list">http://lists.dot.net/mailman/listinfo/mono-devel-list</a>
</pre>
</blockquote>
<br>
</body>
</html>
--------------FB5D0FE3265B8DB38C421570--
--===============1715578260771353598==
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: base64
Content-Disposition: inline
X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KTW9uby1kZXZl
bC1saXN0IG1haWxpbmcgbGlzdApNb25vLWRldmVsLWxpc3RAbGlzdHMuZG90Lm5ldApodHRwOi8v
bGlzdHMuZG90Lm5ldC9tYWlsbWFuL2xpc3RpbmZvL21vbm8tZGV2ZWwtbGlzdAo=
--===============1715578260771353598==--