Marshalling Simple Structures


The .NET Compact Framework can marshal simple structures between the managed and native worlds . Unlike the full desktop .NET Framework, there are strong restrictions governing what kinds of structures can be marshalled automatically.

First, the .NET Compact Framework marshals all simple structures by reference. Thus, the native side sees parameters that are structures as pointers to the structure. As such, the native code can alter the contents of structures, and the alterations are visible as side effects on the managed side.

Another important rule is that only references to " shallow " structures can be marshalled automatically. This means that the structure can contain an arbitrary number of fundamental data types, as described in previous sections, but the structure cannot contain strings or nested structures. For example, the first structure shown below can be marshalled automatically, but the second cannot.

The following is a structure that can be automatically marshalled:

 
 C# public struct MarshallableStruct {    public int m_Int;    public char m_Char;    public Int32 m_DWORD;    public bool m_Bool; } VB Public Structure MarshallableStruct    Public m_Int As Integer    Public m_Char As Char    Public m_DWORD As Int32    Public m_Bool As Boolean End Structure 

The following is a structure that cannot be automatically marshalled:

 
 C# public struct NestedStruct {    public int m_Int;    public char m_Char; } public struct CannotAutoMarshal {    public int m_Int;    public NestedStruct m_Nested;    public Int32 m_DWORD;    public bool m_Bool; } VB Public Structure NestedStruct    Public m_Int As Integer    Public m_Char As Char End Structure Public Structure CannotAutoMarshal    Public m_Int As Integer    Public m_Nested As NestedStruct    Public m_DWORD As Int32    Public m_Bool As Boolean End Structure 

Complex structures that cannot be marshalled automatically and structures with strings in them can be passed to native code, but doing so requires manual marshalling. The next section describes how to do manual marshalling.

Once you understand the rules, passing shallow structures into native code is not significantly different from passing fundamental data types into native code. You need to declare the native function that is passed the structure. You also need to create a structure in managed code that has a compatible layout to the structure you create in native code. For example, if your managed structure is composed of two Int32 values, then you also need a structure that houses two 32-bit integers on the native side.

The code in Listing 12.4 is derived from the MarshalShallowStruct sample application. It shows the structure and method declarations in C# and Visual Basic to set up for a call to a native C function called ManipulateStruct . It also shows the corresponding C code for the ManipulateStruct .

Listing 12.4 Structure and method declarations in C# and Visual Basic to set up for a call to a native C function called ManipulateStruct
 C# // Structure declaration public struct ShallowStruct {    public int m_Int;    public char m_Char;    public Int32 m_DWORD;    public bool m_Bool; } // Method declaration // Method invocation on native function // Set up input... ShallowStruct in_Struct = new ShallowStruct(); in_Struct.m_Int = Convert.ToInt32(4); in_Struct.m_Char = Convert.ToChar('C'); in_Struct.m_DWORD = Convert.ToInt32(4434); in_Struct.m_Bool = true; ShallowStruct out_Struct = new ShallowStruct(); // Call native function ManipulateStruct(ref in_Struct, ref out_Struct); // out_Struct has been altered by the native code implementation // of ManipulateStruct VB ' Structure declaration Public Structure ShallowStruct    Public m_Int As Integer    Public m_Char As Char    Public m_DWORD As Int32    Public m_Bool As Boolean    End Structure ' Method declaration Declare Sub ManipulateStruct Lib "ManipulateStruct.dll" (ByRef         in_ShallowStruct As ShallowStruct,         ByRef out_ShallowStruct As ShallowStruct) ' Method invocation on native function ' Set up input... Dim in_Struct As ShallowStruct = New ShallowStruct in_Struct.m_Int = Convert.ToInt32(4) in_Struct.m_Char = Convert.ToChar("C") in_Struct.m_DWORD = Convert.ToInt32(4434) in_Struct.m_Bool = True Dim out_Struct As ShallowStruct = New ShallowStruct ' Call native function ManipulateStruct(in_Struct, out_Struct) ' out_Struct has been altered by the native code implementation ' of ManipulateStruct Native C implementation for ManipulateStruct /* Structure declaration */ struct ShallowStruct {    int    m_Int;    char   m_Char;    DWORD  m_DWORD;    bool   m_Bool; }; /* ManipulateStruct function implementation */ void __cdecl ManipulateStruct(ShallowStruct * in_ShallowStruct,         ShallowStruct * out_ShallowStruct) {    out_ShallowStruct->m_Int   = in_ShallowStruct->m_Int + 1;    out_ShallowStruct->m_Char  = in_ShallowStruct->m_Char + 1;    out_ShallowStruct->m_DWORD = in_ShallowStruct->m_DWORD + 1;    out_ShallowStruct->m_Bool  = (in_ShallowStruct->m_Bool !=            true); } 

Marshalling Shallow Structures with the MarshalShallowStruct Sample Application

The MarshalShallowStruct sample application demonstrates an end-to-end scenario for calling a native function and passing automatically marshalled shallow structures as parameters. The sample application is located in the folder \SampleApplications\Chapter12 . There are C# and Visual Basic versions.

MarshalShallowStruct uses a native DLL, ManipulateStruct.dll . The source code for this DLL is in the folder \SampleApplications\Chapter12\NativeBinaries\ManipulateStruct . Just like the SquareAnInt sample application, there are also pre-compiled DLL binaries in the \SampleApplications\Chapter12\NativeBinaries\ManipulateStruct directory. Each binary is in its own subdirectory according to the hardware and operating system for which the DLL was built.

To use the MarshalShallowStruct application, build and deploy the managed project to your device. Then copy the appropriate ManipulateStruct.dll library to your device, either to the \Windows directory or the directory where the managed executable, ManipulateStruct.exe , resides. You can now launch the application.

When MarshalShallowStruct launches, it shows a form with four fields: one for an integer, one for a character, one for a DWORD value, and one for a Boolean value. Each holds a default value. When you click the button labeled Update Struct, the application passes a structure holding each field's value to the native function ManipulateStruct() that resides in ManipulateStruct.dll .

The ManipulateStruct() function increments each field in the shallow structure passed to it. When the function returns, the managed application updates the main form to display the new values that were set by the native code.



Microsoft.NET Compact Framework Kick Start
Microsoft .NET Compact Framework Kick Start
ISBN: 0672325705
EAN: 2147483647
Year: 2003
Pages: 206

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net