@@ -50,10 +50,13 @@ in your managed code. Let's show a message box from a command-line application:
5050
5151 public class Program {
5252
53+ // Import user32.dll (containing the function we need) and define
54+ // the method corresponding to the native function.
5355 [DllImport (" user32.dll" )]
5456 public static extrn int MessageBox (IntPtr hWnd , String text , String caption , int options );
5557
5658 public static void Main (string [] args ) {
59+ // Invoke the function as a regular managed method.
5760 MessageBox (IntPtr .Zero , " Command-line message box" , " Attention!" , 0 );
5861 }
5962 }
@@ -148,17 +151,22 @@ else.
148151
149152 class Program {
150153
154+ // Define a delegate that corresponds to the unmanaged function.
151155 delegate bool EnumWC (IntPtr hwnd , IntPtr lParam );
152156
157+ // Import user32.dll (containing the function we need) and define
158+ // the method corresponding to the native function.
153159 [DllImport (" user32.dll" )]
154160 static extern int EnumWindows (EnumWC hWnd , IntPtr lParam );
155161
162+ // Define the implementation of the delegate; here, we simply output the window handle.
156163 static bool OutputWindow (IntPtr hwnd , IntPtr lParam ) {
157164 Console .WriteLine (hwnd .ToInt64 ());
158165 return true ;
159166 }
160167
161168 static void Main (string [] args ) {
169+ // Invoke the method; note the delegate as a first parameter.
162170 EnumWindows (OutputWindow , IntPtr .Zero );
163171 }
164172 }
@@ -197,46 +205,48 @@ The said function has the following signature:
197205 using System .Runtime .InteropServices ;
198206
199207 namespace PInvokeSamples {
200- public static class Program {
201-
202- // Define a delegate that has the same signature as the native function.
203- delegate int DirClbk (string fName , StatClass stat , int typeFlag );
204-
205- // Import the libc and define the method to represent the native function.
206- [DllImport (" libc.so.6" )]
207- static extern int ftw (string dirpath , DirClbk cl , int descriptors );
208-
209- // Implement the above DirClbk delegate; this one just prints out the filename that is passed to it.
210- static int DisplayEntry (string fName , StatClass stat , int typeFlag ) {
211- Console .WriteLine (fName );
212- return 0 ;
213- }
214-
215- public static void Main (string [] args ){
216- // Call the native function. Note the second parameter which represents the delegate (callback).
217- ftw (" ." , DisplayEntry , 10 );
218- }
219- }
220-
221- // The native callback takes a pointer to a struct. The below class
222- // represents that struct in managed code. You can find more information
223- // about this in the section on marshalling below.
224- [StructLayout (LayoutKind .Sequential )]
225- public class StatClass {
226- public uint DeviceID ;
227- public uint InodeNumber ;
228- public uint Mode ;
229- public uint HardLinks ;
230- public uint UserID ;
231- public uint GroupID ;
232- public uint SpecialDeviceID ;
233- public ulong Size ;
234- public ulong BlockSize ;
235- public uint Blocks ;
236- public long TimeLastAccess ;
237- public long TimeLastModification ;
238- public long TimeLastStatusChange ;
239- }
208+ public static class Program {
209+
210+ // Define a delegate that has the same signature as the native function.
211+ delegate int DirClbk (string fName , StatClass stat , int typeFlag );
212+
213+ // Import the libc and define the method to represent the native function.
214+ [DllImport (" libc.so.6" )]
215+ static extern int ftw (string dirpath , DirClbk cl , int descriptors );
216+
217+ // Implement the above DirClbk delegate;
218+ // this one just prints out the filename that is passed to it.
219+ static int DisplayEntry (string fName , StatClass stat , int typeFlag ) {
220+ Console .WriteLine (fName );
221+ return 0 ;
222+ }
223+
224+ public static void Main (string [] args ){
225+ // Call the native function.
226+ // Note the second parameter which represents the delegate (callback).
227+ ftw (" ." , DisplayEntry , 10 );
228+ }
229+ }
230+
231+ // The native callback takes a pointer to a struct. The below class
232+ // represents that struct in managed code. You can find more information
233+ // about this in the section on marshalling below.
234+ [StructLayout (LayoutKind .Sequential )]
235+ public class StatClass {
236+ public uint DeviceID ;
237+ public uint InodeNumber ;
238+ public uint Mode ;
239+ public uint HardLinks ;
240+ public uint UserID ;
241+ public uint GroupID ;
242+ public uint SpecialDeviceID ;
243+ public ulong Size ;
244+ public ulong BlockSize ;
245+ public uint Blocks ;
246+ public long TimeLastAccess ;
247+ public long TimeLastModification ;
248+ public long TimeLastStatusChange ;
249+ }
240250 }
241251
242252
@@ -259,14 +269,16 @@ to the ``DllImport`` attribute, as OS X keeps ``libc`` in a different place.
259269 [DllImport (" libSystem.dylib" )]
260270 static extern int ftw (string dirpath , DirClbk cl , int descriptors );
261271
262- // Implement the above DirClbk delegate; this one just prints out the filename that is passed to it.
272+ // Implement the above DirClbk delegate;
273+ // this one just prints out the filename that is passed to it.
263274 static int DisplayEntry (string fName , StatClass stat , int typeFlag ) {
264275 Console .WriteLine (fName );
265276 return 0 ;
266277 }
267278
268279 public static void Main (string [] args ){
269- // Call the native function. Note the second parameter which represents the delegate (callback).
280+ // Call the native function.
281+ // Note the second parameter which represents the delegate (callback).
270282 ftw (" ." , DisplayEntry , 10 );
271283 }
272284 }
@@ -299,7 +311,7 @@ to writing quality native interop code, let's take a look at what happens when
299311the runtime *marshals * the types.
300312
301313Type marshalling
302- ^^^^^^^^^^^^^^^^
314+ ----------------
303315**Marshalling ** is the process of transforming types when they need to cross the
304316managed boundary into native and vice versa.
305317
@@ -318,6 +330,9 @@ ANSI string, we could do it like this:
318330 [DllImport (" somenativelibrary.dll" ]
319331 static extern int MethodA ([MarshalAs (UnmanagedType .LPStr ) string parameter );
320332
333+
334+ Marshalling classes and structs
335+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
321336Another aspect of type marshalling is how to pass in a struct to an unmanaged method .
322337For instance , some of the unmanaged methods require a struct as a parameter .
323338In these cases , we need to create a corresponding struct or a class in managed
0 commit comments