Browse Source

Handle DataLogger disposal with _ptr is null.

pull/859/head
Canming Huang 2 years ago
parent
commit
975dd71071
  1. 342
      Emgu.CV/Util/DataLogger.cs

342
Emgu.CV/Util/DataLogger.cs

@ -9,180 +9,186 @@ using Emgu.Util;
namespace Emgu.CV.Util
{
/// <summary>
/// A DataLogger for unmanaged code to log data back to managed code, using callback.
/// </summary>
public class DataLogger : UnmanagedObject
{
private int _loggerId;
/// <summary>
/// Create a MessageLogger and register the callback function
/// </summary>
/// <param name="logLevel">The log level.</param>
public DataLogger(int logLevel)
{
lock (typeof(DataLoggerHelper))
{
_loggerId = DataLoggerHelper.TotalLoggerCount;
DataLoggerHelper.TotalLoggerCount++;
}
_ptr = CvInvoke.DataLoggerCreate(logLevel, _loggerId);
CvInvoke.DataLoggerRegisterCallback(_ptr, DataLoggerHelper.Handler);
DataLoggerHelper.OnDataReceived += this.HelperDataHandler;
}
/// <summary>
/// The event that will be raised when the unmanaged code send over data
/// </summary>
public event EventHandler<EventArgs<IntPtr>> OnDataReceived;
private void HelperDataHandler(IntPtr data, int loggerId)
{
if (loggerId == _loggerId && OnDataReceived != null)
{
OnDataReceived(this, new EventArgs<IntPtr>(data));
}
}
/// <summary>
/// Log some data
/// </summary>
/// <param name="data">Pointer to some unmanaged data</param>
/// <param name="logLevel">The logLevel. The Log function only logs when the <paramref name="logLevel"/> is greater or equals to the DataLogger's logLevel</param>
public void Log(IntPtr data, int logLevel)
{
CvInvoke.DataLoggerLog(_ptr, data, logLevel);
}
/// <summary>
/// Release the DataLogger and all the unmanaged memory associated with it.
/// </summary>
protected override void DisposeObject()
{
CvInvoke.DataLoggerRelease(ref _ptr);
DataLoggerHelper.OnDataReceived -= this.HelperDataHandler;
}
}
/// <summary>
/// A generic version of the DataLogger
/// </summary>
/// <typeparam name="T">The supported type includes System.String and System.ValueType</typeparam>
public class DataLogger<T> : DisposableObject
{
private DataLogger _logger;
private EventHandler<EventArgs<IntPtr>> _handler;
/// <summary>
/// Create a new DataLogger
/// </summary>
/// <param name="logLevel">The log level.</param>
public DataLogger(int logLevel)
{
_logger = new DataLogger(logLevel);
_handler = DataHandler;
_logger.OnDataReceived += _handler;
}
/// <summary>
/// The event that will be raised when the unmanaged code send over data
/// </summary>
public event EventHandler<EventArgs<T>> OnDataReceived;
/// <summary>
/// Log some data
/// </summary>
/// <param name="data">The data to be logged</param>
/// <param name="logLevel">The logLevel. The Log function only logs when the <paramref name="logLevel"/> is greater or equals to the DataLogger's logLevel</param>
public void Log(T data, int logLevel)
{
if (typeof(T) == typeof(String))
{
String d = data as String;
IntPtr unmanagedData = Marshal.StringToHGlobalAnsi(d);
_logger.Log(unmanagedData, logLevel);
Marshal.FreeHGlobal(unmanagedData);
} else
{
IntPtr unmanagedData = Marshal.AllocHGlobal(Toolbox.SizeOf<T>());
Marshal.StructureToPtr(data, unmanagedData, false);
_logger.Log(unmanagedData, logLevel);
Marshal.FreeHGlobal(unmanagedData);
}
}
private void DataHandler(Object sender, EventArgs<IntPtr> e)
{
if (OnDataReceived != null)
{
T result;
/// <summary>
/// A DataLogger for unmanaged code to log data back to managed code, using callback.
/// </summary>
public class DataLogger : UnmanagedObject
{
private int _loggerId;
/// <summary>
/// Create a MessageLogger and register the callback function
/// </summary>
/// <param name="logLevel">The log level.</param>
public DataLogger(int logLevel)
{
lock (typeof(DataLoggerHelper))
{
_loggerId = DataLoggerHelper.TotalLoggerCount;
DataLoggerHelper.TotalLoggerCount++;
}
_ptr = CvInvoke.DataLoggerCreate(logLevel, _loggerId);
CvInvoke.DataLoggerRegisterCallback(_ptr, DataLoggerHelper.Handler);
DataLoggerHelper.OnDataReceived += this.HelperDataHandler;
}
/// <summary>
/// The event that will be raised when the unmanaged code send over data
/// </summary>
public event EventHandler<EventArgs<IntPtr>> OnDataReceived;
private void HelperDataHandler(IntPtr data, int loggerId)
{
if (loggerId == _loggerId && OnDataReceived != null)
{
OnDataReceived(this, new EventArgs<IntPtr>(data));
}
}
/// <summary>
/// Log some data
/// </summary>
/// <param name="data">Pointer to some unmanaged data</param>
/// <param name="logLevel">The logLevel. The Log function only logs when the <paramref name="logLevel"/> is greater or equals to the DataLogger's logLevel</param>
public void Log(IntPtr data, int logLevel)
{
CvInvoke.DataLoggerLog(_ptr, data, logLevel);
}
/// <summary>
/// Release the DataLogger and all the unmanaged memory associated with it.
/// </summary>
protected override void DisposeObject()
{
if (_ptr != IntPtr.Zero)
CvInvoke.DataLoggerRelease(ref _ptr);
DataLoggerHelper.OnDataReceived -= this.HelperDataHandler;
}
}
/// <summary>
/// A generic version of the DataLogger
/// </summary>
/// <typeparam name="T">The supported type includes System.String and System.ValueType</typeparam>
public class DataLogger<T> : DisposableObject
{
private DataLogger _logger;
private EventHandler<EventArgs<IntPtr>> _handler;
/// <summary>
/// Create a new DataLogger
/// </summary>
/// <param name="logLevel">The log level.</param>
public DataLogger(int logLevel)
{
_logger = new DataLogger(logLevel);
_handler = DataHandler;
_logger.OnDataReceived += _handler;
}
/// <summary>
/// The event that will be raised when the unmanaged code send over data
/// </summary>
public event EventHandler<EventArgs<T>> OnDataReceived;
/// <summary>
/// Log some data
/// </summary>
/// <param name="data">The data to be logged</param>
/// <param name="logLevel">The logLevel. The Log function only logs when the <paramref name="logLevel"/> is greater or equals to the DataLogger's logLevel</param>
public void Log(T data, int logLevel)
{
if (typeof(T) == typeof(String))
{
result = (T) ((Object) Marshal.PtrToStringAnsi(e.Value));
} else
String d = data as String;
IntPtr unmanagedData = Marshal.StringToHGlobalAnsi(d);
_logger.Log(unmanagedData, logLevel);
Marshal.FreeHGlobal(unmanagedData);
}
else
{
result = Marshal.PtrToStructure<T>(e.Value);
IntPtr unmanagedData = Marshal.AllocHGlobal(Toolbox.SizeOf<T>());
Marshal.StructureToPtr(data, unmanagedData, false);
_logger.Log(unmanagedData, logLevel);
Marshal.FreeHGlobal(unmanagedData);
}
OnDataReceived(this, new EventArgs<T>(result));
}
}
/// <summary>
/// Pointer to the unmanaged object
/// </summary>
public IntPtr Ptr
{
get
{
return _logger.Ptr;
}
}
/// <summary>
/// Implicit operator for IntPtr
/// </summary>
/// <param name="obj">The DataLogger</param>
/// <returns>The unmanaged pointer for this DataLogger</returns>
public static implicit operator IntPtr(DataLogger<T> obj)
{
return obj == null ? IntPtr.Zero : obj.Ptr;
}
/// <summary>
/// Release the unmanaged memory associated with this DataLogger
/// </summary>
protected override void DisposeObject()
{
_logger.OnDataReceived -= _handler;
_logger.Dispose();
}
}
internal static class DataLoggerHelper
{
/// <summary>
/// The event that will be raised when the unmanaged code send over data
/// </summary>
public static event DataCallback OnDataReceived;
[UnmanagedFunctionPointer(CvInvoke.CvCallingConvention)]
public delegate void DataCallback(IntPtr data, int loggerId);
public static DataCallback Handler = DataHandler;
}
private void DataHandler(Object sender, EventArgs<IntPtr> e)
{
if (OnDataReceived != null)
{
T result;
if (typeof(T) == typeof(String))
{
result = (T)((Object)Marshal.PtrToStringAnsi(e.Value));
}
else
{
result = Marshal.PtrToStructure<T>(e.Value);
}
OnDataReceived(this, new EventArgs<T>(result));
}
}
/// <summary>
/// Pointer to the unmanaged object
/// </summary>
public IntPtr Ptr
{
get
{
return _logger.Ptr;
}
}
/// <summary>
/// Implicit operator for IntPtr
/// </summary>
/// <param name="obj">The DataLogger</param>
/// <returns>The unmanaged pointer for this DataLogger</returns>
public static implicit operator IntPtr(DataLogger<T> obj)
{
return obj == null ? IntPtr.Zero : obj.Ptr;
}
/// <summary>
/// Release the unmanaged memory associated with this DataLogger
/// </summary>
protected override void DisposeObject()
{
if (_logger != null)
{
_logger.OnDataReceived -= _handler;
_logger.Dispose();
}
}
}
internal static class DataLoggerHelper
{
/// <summary>
/// The event that will be raised when the unmanaged code send over data
/// </summary>
public static event DataCallback OnDataReceived;
[UnmanagedFunctionPointer(CvInvoke.CvCallingConvention)]
public delegate void DataCallback(IntPtr data, int loggerId);
public static DataCallback Handler = DataHandler;
#if __IOS__
//[ObjCRuntime.MonoPInvokeCallback(typeof(DataLoggerHelper.DataCallback))]
#endif
public static void DataHandler(IntPtr data, int loggerId)
{
if (OnDataReceived != null)
OnDataReceived(data, loggerId);
}
public static volatile int TotalLoggerCount = 0;
}
public static void DataHandler(IntPtr data, int loggerId)
{
if (OnDataReceived != null)
OnDataReceived(data, loggerId);
}
public static volatile int TotalLoggerCount = 0;
}
}
Loading…
Cancel
Save