1 // Log.cs - Wrapper for message logging functions 2 // 3 // Authors: 4 // Gonzalo Paniagua Javier (gonzalo@ximian.com) 5 // 6 // 7 // Copyright (c) 2002 Gonzalo Paniagua 8 // 9 // This program is free software; you can redistribute it and/or 10 // modify it under the terms of version 2 of the Lesser GNU General 11 // Public License as published by the Free Software Foundation. 12 // 13 // This program is distributed in the hope that it will be useful, 14 // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 // Lesser General Public License for more details. 17 // 18 // You should have received a copy of the GNU Lesser General Public 19 // License along with this program; if not, write to the 20 // Free Software Foundation, Inc., 59 Temple Place - Suite 330, 21 // Boston, MA 02111-1307, USA. 22 23 // 24 25 namespace GLib { 26 27 using System; 28 using System.Runtime.InteropServices; 29 LogFunc(string log_domain, LogLevelFlags log_level, string message)30 public delegate void LogFunc (string log_domain, LogLevelFlags log_level, string message); 31 PrintFunc(string message)32 public delegate void PrintFunc (string message); 33 34 [Flags] 35 public enum LogLevelFlags : int 36 { 37 /* log flags */ 38 FlagRecursion = 1 << 0, 39 FlagFatal = 1 << 1, 40 41 /* GLib log levels */ 42 Error = 1 << 2, /* always fatal */ 43 Critical = 1 << 3, 44 Warning = 1 << 4, 45 Message = 1 << 5, 46 Info = 1 << 6, 47 Debug = 1 << 7, 48 49 /* Convenience values */ 50 AllButFatal = 253, 51 AllButRecursion = 254, 52 All = 255, 53 54 FlagMask = 3, 55 LevelMask = unchecked ((int) 0xFFFFFFFC) 56 } 57 58 public class Log { 59 60 [UnmanagedFunctionPointer (CallingConvention.Cdecl)] LogFuncNative(IntPtr log_domain, LogLevelFlags flags, IntPtr message, IntPtr user_data)61 delegate void LogFuncNative (IntPtr log_domain, LogLevelFlags flags, IntPtr message, IntPtr user_data); 62 63 static LogFuncNative native_handler; 64 NativeCallback(IntPtr log_domain_native, LogLevelFlags flags, IntPtr message_native, IntPtr user_data)65 static void NativeCallback (IntPtr log_domain_native, LogLevelFlags flags, IntPtr message_native, IntPtr user_data) 66 { 67 if (user_data == IntPtr.Zero) 68 return; 69 string log_domain = Marshaller.Utf8PtrToString (log_domain_native); 70 string message = Marshaller.Utf8PtrToString (message_native); 71 GCHandle gch = (GCHandle) user_data; 72 LogFunc func = gch.Target as LogFunc; 73 if (func != null) 74 func (log_domain, flags, message); 75 } 76 77 [UnmanagedFunctionPointer (CallingConvention.Cdecl)] PrintFuncNative(IntPtr message)78 delegate void PrintFuncNative (IntPtr message); 79 80 class PrintHelper { 81 82 PrintFuncNative native; 83 PrintFunc managed; 84 PrintHelper(PrintFuncNative native)85 public PrintHelper (PrintFuncNative native) 86 { 87 this.native = native; 88 } 89 PrintHelper(PrintFunc managed)90 public PrintHelper (PrintFunc managed) 91 { 92 this.managed = managed; 93 GCHandle.Alloc (this); 94 } 95 Callback(IntPtr nmessage)96 void Callback (IntPtr nmessage) 97 { 98 string message = Marshaller.Utf8PtrToString (nmessage); 99 managed (message); 100 } 101 Invoke(string message)102 void Invoke (string message) 103 { 104 IntPtr nmessage = Marshaller.StringToPtrGStrdup (message); 105 native (nmessage); 106 Marshaller.Free (nmessage); 107 } 108 109 public PrintFuncNative Handler { 110 get { return new PrintFuncNative (Callback); } 111 } 112 113 public PrintFunc Invoker { 114 get { return new PrintFunc (Invoke); } 115 } 116 } 117 118 static System.Collections.Generic.Dictionary<uint, GCHandle> handlers; 119 EnsureHash()120 static void EnsureHash () 121 { 122 if (handlers == null) 123 handlers = new System.Collections.Generic.Dictionary<uint, GCHandle> (); 124 } 125 126 [DllImport (Global.GLibNativeDll, CallingConvention = CallingConvention.Cdecl)] g_logv(IntPtr log_domain, LogLevelFlags flags, IntPtr message)127 static extern void g_logv (IntPtr log_domain, LogLevelFlags flags, IntPtr message); 128 WriteLog(string logDomain, LogLevelFlags flags, string format, params object [] args)129 public void WriteLog (string logDomain, LogLevelFlags flags, string format, params object [] args) 130 { 131 IntPtr ndom = Marshaller.StringToPtrGStrdup (logDomain); 132 IntPtr nmessage = Marshaller.StringToPtrGStrdup (String.Format (format, args)); 133 g_logv (ndom, flags, nmessage); 134 Marshaller.Free (ndom); 135 Marshaller.Free (nmessage); 136 } 137 138 [DllImport (Global.GLibNativeDll, CallingConvention = CallingConvention.Cdecl)] g_log_set_handler(IntPtr log_domain, LogLevelFlags flags, LogFuncNative log_func, IntPtr user_data)139 static extern uint g_log_set_handler (IntPtr log_domain, LogLevelFlags flags, LogFuncNative log_func, IntPtr user_data); 140 SetLogHandler(string logDomain, LogLevelFlags flags, LogFunc logFunc)141 public static uint SetLogHandler (string logDomain, LogLevelFlags flags, LogFunc logFunc) 142 { 143 if (native_handler == null) 144 native_handler = new LogFuncNative (NativeCallback); 145 146 IntPtr ndom = Marshaller.StringToPtrGStrdup (logDomain); 147 GCHandle gch = GCHandle.Alloc (logFunc); 148 uint result = g_log_set_handler (ndom, flags, native_handler, (IntPtr) gch); 149 Marshaller.Free (ndom); 150 EnsureHash (); 151 handlers [result] = gch; 152 return result; 153 } 154 155 [DllImport (Global.GLibNativeDll, CallingConvention = CallingConvention.Cdecl)] g_log_remove_handler(IntPtr log_domain, uint handler_id)156 static extern uint g_log_remove_handler (IntPtr log_domain, uint handler_id); 157 RemoveLogHandler(string logDomain, uint handlerID)158 public static void RemoveLogHandler (string logDomain, uint handlerID) 159 { 160 if (handlers != null && handlers.ContainsKey (handlerID)) { 161 handlers [handlerID].Free (); 162 handlers.Remove (handlerID); 163 } 164 165 IntPtr ndom = Marshaller.StringToPtrGStrdup (logDomain); 166 g_log_remove_handler (ndom, handlerID); 167 Marshaller.Free (ndom); 168 } 169 170 [DllImport (Global.GLibNativeDll, CallingConvention = CallingConvention.Cdecl)] g_set_print_handler(PrintFuncNative handler)171 static extern PrintFuncNative g_set_print_handler (PrintFuncNative handler); 172 SetPrintHandler(PrintFunc handler)173 public static PrintFunc SetPrintHandler (PrintFunc handler) 174 { 175 PrintHelper helper = new PrintHelper (handler); 176 PrintFuncNative prev = g_set_print_handler (helper.Handler); 177 helper = new PrintHelper (prev); 178 return helper.Invoker; 179 } 180 181 [DllImport (Global.GLibNativeDll, CallingConvention = CallingConvention.Cdecl)] g_set_printerr_handler(PrintFuncNative handler)182 static extern PrintFuncNative g_set_printerr_handler (PrintFuncNative handler); 183 SetPrintErrorHandler(PrintFunc handler)184 public static PrintFunc SetPrintErrorHandler (PrintFunc handler) 185 { 186 PrintHelper helper = new PrintHelper (handler); 187 PrintFuncNative prev = g_set_printerr_handler (helper.Handler); 188 helper = new PrintHelper (prev); 189 return helper.Invoker; 190 } 191 192 [DllImport (Global.GLibNativeDll, CallingConvention = CallingConvention.Cdecl)] g_log_default_handler(IntPtr log_domain, LogLevelFlags log_level, IntPtr message, IntPtr unused_data)193 static extern void g_log_default_handler (IntPtr log_domain, LogLevelFlags log_level, IntPtr message, IntPtr unused_data); 194 DefaultHandler(string logDomain, LogLevelFlags logLevel, string message)195 public static void DefaultHandler (string logDomain, LogLevelFlags logLevel, string message) 196 197 { 198 IntPtr ndom = Marshaller.StringToPtrGStrdup (logDomain); 199 IntPtr nmess = Marshaller.StringToPtrGStrdup (message); 200 g_log_default_handler (ndom, logLevel, nmess, IntPtr.Zero); 201 Marshaller.Free (ndom); 202 Marshaller.Free (nmess); 203 } 204 205 [DllImport (Global.GLibNativeDll, CallingConvention = CallingConvention.Cdecl)] g_log_set_always_fatal(LogLevelFlags fatal_mask)206 extern static LogLevelFlags g_log_set_always_fatal (LogLevelFlags fatal_mask); 207 SetAlwaysFatal(LogLevelFlags fatalMask)208 public static LogLevelFlags SetAlwaysFatal (LogLevelFlags fatalMask) 209 { 210 return g_log_set_always_fatal (fatalMask); 211 } 212 213 [DllImport (Global.GLibNativeDll, CallingConvention = CallingConvention.Cdecl)] g_log_set_fatal_mask(IntPtr log_domain, LogLevelFlags fatal_mask)214 extern static LogLevelFlags g_log_set_fatal_mask (IntPtr log_domain, LogLevelFlags fatal_mask); 215 SetAlwaysFatal(string logDomain, LogLevelFlags fatalMask)216 public static LogLevelFlags SetAlwaysFatal (string logDomain, LogLevelFlags fatalMask) 217 { 218 IntPtr ndom = Marshaller.StringToPtrGStrdup (logDomain); 219 LogLevelFlags result = g_log_set_fatal_mask (ndom, fatalMask); 220 Marshaller.Free (ndom); 221 return result; 222 } 223 224 class Invoker { 225 226 LogFuncNative native; 227 Invoker(LogFuncNative native)228 public Invoker (LogFuncNative native) 229 { 230 this.native = native; 231 } 232 Invoke(string log_domain, LogLevelFlags flags, string message)233 void Invoke (string log_domain, LogLevelFlags flags, string message) 234 { 235 IntPtr ndom = Marshaller.StringToPtrGStrdup (log_domain); 236 IntPtr nmess = Marshaller.StringToPtrGStrdup (message); 237 native (ndom, flags, nmess, IntPtr.Zero); 238 Marshaller.Free (ndom); 239 Marshaller.Free (nmess); 240 } 241 242 public LogFunc Handler { 243 get { return new LogFunc (Invoke); } 244 } 245 } 246 247 [DllImport (Global.GLibNativeDll, CallingConvention = CallingConvention.Cdecl)] g_log_set_default_handler(LogFuncNative log_func, IntPtr user_data)248 extern static LogFuncNative g_log_set_default_handler (LogFuncNative log_func, IntPtr user_data); 249 SetDefaultHandler(LogFunc log_func)250 public static LogFunc SetDefaultHandler (LogFunc log_func) 251 { 252 if (native_handler == null) 253 native_handler = new LogFuncNative (NativeCallback); 254 255 LogFuncNative prev = g_log_set_default_handler (native_handler, (IntPtr) GCHandle.Alloc (log_func)); 256 if (prev == null) 257 return null; 258 Invoker invoker = new Invoker (prev); 259 return invoker.Handler; 260 } 261 262 /* 263 * Some common logging methods. 264 * 265 * Sample usage: 266 * 267 * // Print the messages for the NULL domain 268 * LogFunc logFunc = new LogFunc (Log.PrintLogFunction); 269 * Log.SetLogHandler (null, LogLevelFlags.All, logFunc); 270 * 271 * // Print messages and stack trace for Gtk critical messages 272 * logFunc = new LogFunc (Log.PrintTraceLogFunction); 273 * Log.SetLogHandler ("Gtk", LogLevelFlags.Critical, logFunc); 274 * 275 */ 276 PrintLogFunction(string domain, LogLevelFlags level, string message)277 public static void PrintLogFunction (string domain, LogLevelFlags level, string message) 278 { 279 Console.WriteLine ("Domain: '{0}' Level: {1}", domain, level); 280 Console.WriteLine ("Message: {0}", message); 281 } 282 PrintTraceLogFunction(string domain, LogLevelFlags level, string message)283 public static void PrintTraceLogFunction (string domain, LogLevelFlags level, string message) 284 { 285 PrintLogFunction (domain, level, message); 286 Console.WriteLine ("Trace follows:\n{0}", new System.Diagnostics.StackTrace ()); 287 } 288 } 289 } 290 291