Inside C# 4 Data Structs
Tuesday, 07 September 2010
Article Index
Inside C# 4 Data Structs
Being exact
Serialising structs
Manual mashaling




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:

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:


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(

followed by the pointer to the handle:

IntPtr lphandle = MarshalToPointer(

The call to the API function is now simple:

result = AVISaveOptions(

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:


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:


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.


What's The Matter With Pointers?

Back in the days when C was the language of choice, pointers meant programming and vice versa. Now in the more sophisticated and abstract days of C#, and even C++, raw pointers are a facility that is  [ ... ]

C# Bit Bashing - The BitConverter

Is C# a high-level or a low-level language? It doesn't really matter - all languages are low-level when you are thinking in terms of bits, and sometimes you just can't avoid thinking in bits.

Other Articles






Last Updated ( Tuesday, 28 September 2010 )

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