Inside C# 4 Data Structs
Tuesday, 07 September 2010
Article Index
Inside C# 4 Data Structs
Being exact
The API
Serialising structs
Manual mashaling
Struct-to-pointer

 

Banner

 

Now that we have mastered the manual marshaling of a simple pointer to a struct the next step is a pointer to a pointer to a struct. Surprisingly this requires nothing new because the struct-to-pointer function will actually convert any data type to an unmanaged pointer – including a pointer.

The  function AVISaveOption is a suitable example as it needs two pointers to pointers as parameters:

[DllImport("avifil32.dll")]
extern static int AVISaveOptions(
IntPtr hWnd,
int uiFlags,
int noStreams,
IntPtr ppavi,
IntPtr ppOptions);

In fact the ppavi parameter is a pointer to a handle (which is itself a pointer) and the ppOptions is a pointer to a pointer to a struct. To call this function we first need the struct:

AVICOMPRESSOPTIONS opts = new 
AVICOMPRESSOPTIONS();

You can look up the definition of the structure in the standard AVI documentation.

Next we need the marshaled pointer to the struct:

IntPtr lpstruct = MarshalToPointer(opts);

and then the pointer to the pointer:

IntPtr lppstruct = MarshalToPointer(
lpstruct);

followed by the pointer to the handle:

IntPtr lphandle = MarshalToPointer(
pStream);

The call to the API function is now simple:

result = AVISaveOptions(
m_hWnd,
ICMF_CHOOSE_KEYFRAME |
ICMF_CHOOSE_DATARATE,
1,
lphandle,
lppstruct);

where the other parameters and constants aren’t of any great interest to us and you can find more details in the API’s documentation.

When the function completes all that is left to do is transfer the data in the unmanaged buffer back into the managed struct:

opts = (AVICOMPRESSOPTIONS) 
MarshalToStruct(lpstruct,
typeof(AVICOMPRESSOPTIONS));

You have to be careful to use the pointer to the struct and not the pointer to the pointer!

Finally we can free all of the unmanaged memory we used:

Marshal.FreeHGlobal(lpstruct);
Marshal.FreeHGlobal(lppstruct);
Marshal.FreeHGlobal(lphandle);

This might all seem complicated. Using pointers-to-pointers is never an easy thing to do and it is one of the reasons that C# makes sure that when you do use pointers then you mark the code as unsafe. However you might like to contemplate just how safe this sort of juggling is and all without an unsafe block in sight.

On the other hand the general principles are very simple. When you pass anything by ref to an API it has to be copied to unmanaged memory and the address of this memory is passed to the function. Normally default marshaling takes care of this and you can ignore it - but it still happens. If you need to go beyond what is provided by the marshaling attributes then you have to perform this copying explicitly.

Banner


.NET Regular Expressions in depth

If you think regular expressions are trivial and boring you've not seen the whole picture. Here we reveal that in .NET they are amazing powerful and not to be missed.



Anonymous Methods In C#

Anonymous methods aren't particularly new, but they have hidden depths and lead on to lambda expressions.


Other Articles

<ASIN:0321658701>
<ASIN:1451531168>

<ASIN:0321637003>

<ASIN:0596800959>

<ASIN:047043452X>

<ASIN:0123745144>



Last Updated ( Tuesday, 28 September 2010 )
 
 

   
RSS feed of all content
I Programmer - full contents
Copyright © 2014 i-programmer.info. All Rights Reserved.
Joomla! is Free Software released under the GNU/GPL License.