1 // A demonstration of a custom marshaler that marshals
2 // unmanaged to managed data.
5 using System.Runtime.InteropServices;
7 public class MyMarshal: ICustomMarshaler
10 // GetInstance() is not part of ICustomMarshaler, but
11 // custom marshalers are required to implement this
13 public static ICustomMarshaler GetInstance (string s)
15 Console.WriteLine ("GetInstance called");
16 return new MyMarshal ();
19 public void CleanUpManagedData (object managedObj)
21 Console.WriteLine ("CleanUpManagedData called");
24 public void CleanUpNativeData (IntPtr pNativeData)
26 Console.WriteLine("CleanUpNativeData called");
27 if (pNativeData != IntPtr.Zero)
28 Marshal.FreeHGlobal (pNativeData);
32 // I really do not understand the purpose of this method
33 // or went it would be called. In fact, Rotor never seems
35 public int GetNativeDataSize ()
37 Console.WriteLine("GetNativeDataSize() called");
41 public IntPtr MarshalManagedToNative (object managedObj)
43 Console.WriteLine("MarshalManagedToNative()");
48 // Convert a pointer to unmanaged data into a System.Object.
49 // This method simply converts the unmanaged Ansi C-string
50 // into a System.String and surrounds it with asterisks
51 // to differentiate it from the default marshaler.
52 public object MarshalNativeToManaged (IntPtr pNativeData)
54 Console.WriteLine("MarshalNativeToManaged()");
55 return "*" + Marshal.PtrToStringAnsi( pNativeData ) + "*";
60 public class time_t_CustomMarshaler : ICustomMarshaler {
62 static time_t_CustomMarshaler marshaler;
66 private time_t_CustomMarshaler ()
68 utc_offset = (int) DateTime.Now.Subtract (DateTime.UtcNow).TotalSeconds;
69 local_epoch = new DateTime (1970, 1, 1, 0, 0, 0);
72 public static ICustomMarshaler GetInstance (string cookie)
74 if (marshaler == null)
75 marshaler = new time_t_CustomMarshaler ();
80 public IntPtr MarshalManagedToNative (object obj)
83 // This method should return a pointer to a memory buffer holding
84 // the unmanaged representation of 'obj'
85 // The first 4 bytes of the buffer is unused (is this really 4 bytes on a 64bit machine?)
86 // The unmanaged function will receive the address of the buffer
90 DateTime dt = (DateTime) obj;
91 int size = Marshal.SizeOf (typeof (int)) + GetNativeDataSize ();
92 IntPtr ptr = Marshal.AllocCoTaskMem (size);
93 int secs = ((int)dt.Subtract (local_epoch).TotalSeconds) + utc_offset;
94 if (GetNativeDataSize () == 4)
95 Marshal.WriteInt32 (ptr, secs);
96 else if (GetNativeDataSize () == 8)
97 Marshal.WriteInt64 (ptr, secs);
99 throw new Exception ("Unexpected native size for time_t.");
104 public void CleanUpNativeData (IntPtr data)
106 Marshal.FreeHGlobal (data);
109 public object MarshalNativeToManaged (IntPtr data)
112 // This function receives the return value of the unmanaged function
119 TimeSpan span = new TimeSpan (0, 0, secs - utc_offset);
120 return local_epoch.Add (span);
123 public void CleanUpManagedData (object obj)
127 [DllImport("libtest")]
128 private static extern int time_t_sizeof ();
130 public int GetNativeDataSize ()
132 return time_t_sizeof ();
138 [DllImport("libtest")]
139 [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(MyMarshal))]
140 private static extern string functionReturningString();
142 [DllImport("libtest", EntryPoint="mono_test_marshal_time_t")]
143 [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(time_t_CustomMarshaler))]
144 private static extern DateTime mono_test_marshal_time_t (
145 [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(time_t_CustomMarshaler))]
148 public static int Main()
150 string res = functionReturningString();
151 Console.WriteLine ("native string function returns {0}", res);
156 DateTime d = DateTime.Now;
157 DateTime d2 = mono_test_marshal_time_t (d);
159 if (((d2 - d).TotalSeconds < 3599) || ((d2 - d).TotalSeconds > 3601))