Marshalling Structures

  • Thread starter Thread starter Kevin Hutchison
  • Start date Start date
K

Kevin Hutchison

Every example I have seen marshals structures containing "blittable" types
by reference. Is it possible to marshal it by value? I am getting the
System.NotSupportedException and every type supported by the marshaller
appears to be sized to 4 bytes (long can only be passed by ref).

Second question - where is GOOD documentation on the .NET CF marshaller?

struct SIMPLE
{
int i;
int j;
}

[DllImport("api.dll")]
public static extern setsimple ( SIMPLE simple );

.....

void foo()
{
SIMPLE mySimple = new SIMPLE();
setsimple( mySimple );
}

.....
 
Thanks, Peter. I have seen those articles and do refer to them.
Unfortunately, my understanding from them is that marshalling structures can
be done without a problem. In fact,
"As mentioned previously, you can pass structures to unmanaged functions
without worrying, as long as the structure contains blittable types. ... ...
Since the structure contains only blittable types (unmanaged DWORD values
that translate to unsigned 32 bit integers, System.UInt32, in the .NET
Compact Framework), the function can be called easily, as shown in the
following snippet."

But, all the examples that I see infact pass structures *by reference*. I
need to pass them by value. My call works by passing the members of the
structure independently.

[DllImport("api.dll")]
public static extern setsimple ( int SIMPLE_i, int SIMPLE_j );

.....

void foo()
{
SIMPLE mySimple = new SIMPLE();
setsimple( mySimple.i, mySimple.j );
}


The API that I am using I have wrapped and working for .NET on the desktop
(yeah!). Enabling the same API for .NET CF looks to require **completely**
rewriting each P/Invoke call. I had expected to have to marshall certain
structures manually, but having to marshall each member of a structure
passed by value independently? ouch.

- K.



Peter Foot said:
There are a pair of good articles here:-

Intro to Marshalling
http://msdn.microsoft.com/mobility/...ary/en-us/dnnetcomp/html/netcfintrointerp.asp
Advanced Marshalling
http://msdn.microsoft.com/mobility/...rary/en-us/dnnetcomp/html/netcfadvinterop.asp

Peter

--
Peter Foot
Windows Embedded MVP
OpenNETCF.org Senior Advisor
www.inthehand.com | www.opennetcf.org

Kevin Hutchison said:
Every example I have seen marshals structures containing "blittable" types
by reference. Is it possible to marshal it by value? I am getting the
System.NotSupportedException and every type supported by the marshaller
appears to be sized to 4 bytes (long can only be passed by ref).

Second question - where is GOOD documentation on the .NET CF marshaller?

struct SIMPLE
{
int i;
int j;
}

[DllImport("api.dll")]
public static extern setsimple ( SIMPLE simple );

....

void foo()
{
SIMPLE mySimple = new SIMPLE();
setsimple( mySimple );
}

....
 
Can you not modify your dll wrapper to accept the struct by reference (a
pointer) then you can use the same technique in desktop or device side code.

Peter

--
Peter Foot
Windows Embedded MVP
OpenNETCF.org Senior Advisor
www.inthehand.com | www.opennetcf.org

Kevin Hutchison said:
Thanks, Peter. I have seen those articles and do refer to them.
Unfortunately, my understanding from them is that marshalling structures can
be done without a problem. In fact,
"As mentioned previously, you can pass structures to unmanaged functions
without worrying, as long as the structure contains blittable types. ... ....
Since the structure contains only blittable types (unmanaged DWORD values
that translate to unsigned 32 bit integers, System.UInt32, in the .NET
Compact Framework), the function can be called easily, as shown in the
following snippet."

But, all the examples that I see infact pass structures *by reference*. I
need to pass them by value. My call works by passing the members of the
structure independently.

[DllImport("api.dll")]
public static extern setsimple ( int SIMPLE_i, int SIMPLE_j );

....

void foo()
{
SIMPLE mySimple = new SIMPLE();
setsimple( mySimple.i, mySimple.j );
}


The API that I am using I have wrapped and working for .NET on the desktop
(yeah!). Enabling the same API for .NET CF looks to require **completely**
rewriting each P/Invoke call. I had expected to have to marshall certain
structures manually, but having to marshall each member of a structure
passed by value independently? ouch.

- K.



Peter Foot said:
There are a pair of good articles here:-

Intro to Marshalling
http://msdn.microsoft.com/mobility/...ary/en-us/dnnetcomp/html/netcfintrointerp.asp
Advanced Marshalling
http://msdn.microsoft.com/mobility/...rary/en-us/dnnetcomp/html/netcfadvinterop.asp
Peter

--
Peter Foot
Windows Embedded MVP
OpenNETCF.org Senior Advisor
www.inthehand.com | www.opennetcf.org

Kevin Hutchison said:
Every example I have seen marshals structures containing "blittable" types
by reference. Is it possible to marshal it by value? I am getting the
System.NotSupportedException and every type supported by the marshaller
appears to be sized to 4 bytes (long can only be passed by ref).

Second question - where is GOOD documentation on the .NET CF marshaller?

struct SIMPLE
{
int i;
int j;
}

[DllImport("api.dll")]
public static extern setsimple ( SIMPLE simple );

....

void foo()
{
SIMPLE mySimple = new SIMPLE();
setsimple( mySimple );
}

....
 
That could be a simpler solution. ...

Mostly, I think I was just frustrated at finding that marshalling structures
was limited to ref. Its simply more time in a project that is pushing
significantly late.

- K.


Peter Foot said:
Can you not modify your dll wrapper to accept the struct by reference (a
pointer) then you can use the same technique in desktop or device side code.

Peter

--
Peter Foot
Windows Embedded MVP
OpenNETCF.org Senior Advisor
www.inthehand.com | www.opennetcf.org

Kevin Hutchison said:
Thanks, Peter. I have seen those articles and do refer to them.
Unfortunately, my understanding from them is that marshalling structures can
be done without a problem. In fact,
"As mentioned previously, you can pass structures to unmanaged functions
without worrying, as long as the structure contains blittable types. ... ...
Since the structure contains only blittable types (unmanaged DWORD values
that translate to unsigned 32 bit integers, System.UInt32, in the .NET
Compact Framework), the function can be called easily, as shown in the
following snippet."

But, all the examples that I see infact pass structures *by reference*. I
need to pass them by value. My call works by passing the members of the
structure independently.

[DllImport("api.dll")]
public static extern setsimple ( int SIMPLE_i, int SIMPLE_j );

....

void foo()
{
SIMPLE mySimple = new SIMPLE();
setsimple( mySimple.i, mySimple.j );
}


The API that I am using I have wrapped and working for .NET on the desktop
(yeah!). Enabling the same API for .NET CF looks to require **completely**
rewriting each P/Invoke call. I had expected to have to marshall certain
structures manually, but having to marshall each member of a structure
passed by value independently? ouch.

- K.



Peter Foot said:
There are a pair of good articles here:-

Intro to Marshalling
http://msdn.microsoft.com/mobility/...rary/en-us/dnnetcomp/html/netcfadvinterop.asp
Peter

--
Peter Foot
Windows Embedded MVP
OpenNETCF.org Senior Advisor
www.inthehand.com | www.opennetcf.org

Every example I have seen marshals structures containing "blittable" types
by reference. Is it possible to marshal it by value? I am getting the
System.NotSupportedException and every type supported by the marshaller
appears to be sized to 4 bytes (long can only be passed by ref).

Second question - where is GOOD documentation on the .NET CF marshaller?

struct SIMPLE
{
int i;
int j;
}

[DllImport("api.dll")]
public static extern setsimple ( SIMPLE simple );

....

void foo()
{
SIMPLE mySimple = new SIMPLE();
setsimple( mySimple );
}

....
 
Sorry for the confusion. You are correct that structures must be passed by
reference. The fundamental limitation of .NETCF marshaling (at least in
version 1) is that only 32-bit integer or pointer values may be passed to a
p/invoke.

If I understand your workaround correctly, you are passing each field of
the structure as a separate argument from managed code and expecting that
to be equivalent to passing the entire structure as a whole by value. In
other words, you expect:

public static extern setsimple ( int SIMPLE_i, int SIMPLE_j );

to be equivalent to the desktop runtime prototype:

public static extern setsimple ( SIMPLE simple );

and both will map to the same native function:

setsimple(struct SIMPLE simple);

This works because the two prototypes are also equivalent in native C code
on your device. But the two prototypes are _not_ equivalent on all hardware
platforms supported by .NETCF, for example on MIPS IV. If you are sure that
your code will only be used on ARM and x86 platforms, it should work
reliably. I am sure you are also aware that this will only work easily if
all fields are defined as 32-bit integers on both the native and managed
sides. If some of the native fields are larger or smaller, they will need
to be split or combined into 32-bit ints on the managed side.

If you need a solution that will work on all devices regardless of CPU, you
will need to pass your structures by reference to a native shim layer.

--------------------
From: "Kevin Hutchison" <[email protected]>
Subject: Re: Marshalling Structures
Date: Wed, 3 Mar 2004 11:42:58 -0500

Thanks, Peter. I have seen those articles and do refer to them.
Unfortunately, my understanding from them is that marshalling structures can
be done without a problem. In fact,
"As mentioned previously, you can pass structures to unmanaged functions
without worrying, as long as the structure contains blittable types. ... ...
Since the structure contains only blittable types (unmanaged DWORD values
that translate to unsigned 32 bit integers, System.UInt32, in the .NET
Compact Framework), the function can be called easily, as shown in the
following snippet."

But, all the examples that I see infact pass structures *by reference*. I
need to pass them by value. My call works by passing the members of the
structure independently.

[DllImport("api.dll")]
public static extern setsimple ( int SIMPLE_i, int SIMPLE_j );

....

void foo()
{
SIMPLE mySimple = new SIMPLE();
setsimple( mySimple.i, mySimple.j );
}


The API that I am using I have wrapped and working for .NET on the desktop
(yeah!). Enabling the same API for .NET CF looks to require **completely**
rewriting each P/Invoke call. I had expected to have to marshall certain
structures manually, but having to marshall each member of a structure
passed by value independently? ouch.

- K.



Peter Foot said:
There are a pair of good articles here:-

Intro to Marshalling
http://msdn.microsoft.com/mobility/understanding/articles/default.aspx?pull
=/library/en-us/dnnetcomp/html/netcfintrointerp.asp
=/library/en-us/dnnetcomp/html/netcfadvinterop.asp
Peter

--
Peter Foot
Windows Embedded MVP
OpenNETCF.org Senior Advisor
www.inthehand.com | www.opennetcf.org

Kevin Hutchison said:
Every example I have seen marshals structures containing "blittable" types
by reference. Is it possible to marshal it by value? I am getting the
System.NotSupportedException and every type supported by the marshaller
appears to be sized to 4 bytes (long can only be passed by ref).

Second question - where is GOOD documentation on the .NET CF marshaller?

struct SIMPLE
{
int i;
int j;
}

[DllImport("api.dll")]
public static extern setsimple ( SIMPLE simple );

....

void foo()
{
SIMPLE mySimple = new SIMPLE();
setsimple( mySimple );
}

....

This posting is provided "AS IS" with no warranties, and confers no rights.
 
Brian -

Thank you for the excellent response! Appreciated. Fortunately, I was
dealing exclusively with ints, uints, and pointers. I was NOT aware of the
limitations regarding supporting the MIPS processor.

Given that I have had need to do more eVC code than expected and have
wrapped a number of other functions, we will be removing the "expanded"
P/Invoke calls and replacing them with shims in the first dot release.

Kevin.


Brian Smith said:
Sorry for the confusion. You are correct that structures must be passed by
reference. The fundamental limitation of .NETCF marshaling (at least in
version 1) is that only 32-bit integer or pointer values may be passed to a
p/invoke.

If I understand your workaround correctly, you are passing each field of
the structure as a separate argument from managed code and expecting that
to be equivalent to passing the entire structure as a whole by value. In
other words, you expect:

public static extern setsimple ( int SIMPLE_i, int SIMPLE_j );

to be equivalent to the desktop runtime prototype:

public static extern setsimple ( SIMPLE simple );

and both will map to the same native function:

setsimple(struct SIMPLE simple);

This works because the two prototypes are also equivalent in native C code
on your device. But the two prototypes are _not_ equivalent on all hardware
platforms supported by .NETCF, for example on MIPS IV. If you are sure that
your code will only be used on ARM and x86 platforms, it should work
reliably. I am sure you are also aware that this will only work easily if
all fields are defined as 32-bit integers on both the native and managed
sides. If some of the native fields are larger or smaller, they will need
to be split or combined into 32-bit ints on the managed side.

If you need a solution that will work on all devices regardless of CPU, you
will need to pass your structures by reference to a native shim layer.

--------------------
From: "Kevin Hutchison" <[email protected]>
Subject: Re: Marshalling Structures
Date: Wed, 3 Mar 2004 11:42:58 -0500

Thanks, Peter. I have seen those articles and do refer to them.
Unfortunately, my understanding from them is that marshalling structures can
be done without a problem. In fact,
"As mentioned previously, you can pass structures to unmanaged functions
without worrying, as long as the structure contains blittable types. ... ..
Since the structure contains only blittable types (unmanaged DWORD values
that translate to unsigned 32 bit integers, System.UInt32, in the .NET
Compact Framework), the function can be called easily, as shown in the
following snippet."

But, all the examples that I see infact pass structures *by reference*. I
need to pass them by value. My call works by passing the members of the
structure independently.

[DllImport("api.dll")]
public static extern setsimple ( int SIMPLE_i, int SIMPLE_j );

....

void foo()
{
SIMPLE mySimple = new SIMPLE();
setsimple( mySimple.i, mySimple.j );
}


The API that I am using I have wrapped and working for .NET on the desktop
(yeah!). Enabling the same API for .NET CF looks to require **completely**
rewriting each P/Invoke call. I had expected to have to marshall certain
structures manually, but having to marshall each member of a structure
passed by value independently? ouch.

- K.



Peter Foot said:
There are a pair of good articles here:-

Intro to Marshalling
http://msdn.microsoft.com/mobility/understanding/articles/default.aspx?pull
=/library/en-us/dnnetcomp/html/netcfintrointerp.asp
Advanced Marshalling
http://msdn.microsoft.com/mobility/understanding/articles/default.aspx?pull
=/library/en-us/dnnetcomp/html/netcfadvinterop.asp
Peter

--
Peter Foot
Windows Embedded MVP
OpenNETCF.org Senior Advisor
www.inthehand.com | www.opennetcf.org

Every example I have seen marshals structures containing "blittable" types
by reference. Is it possible to marshal it by value? I am getting the
System.NotSupportedException and every type supported by the marshaller
appears to be sized to 4 bytes (long can only be passed by ref).

Second question - where is GOOD documentation on the .NET CF marshaller?

struct SIMPLE
{
int i;
int j;
}

[DllImport("api.dll")]
public static extern setsimple ( SIMPLE simple );

....

void foo()
{
SIMPLE mySimple = new SIMPLE();
setsimple( mySimple );
}

....

This posting is provided "AS IS" with no warranties, and confers no rights.
 
Back
Top