Skip to content

Instantly share code, notes, and snippets.

@RyuaNerin
Last active April 5, 2016 23:41
Show Gist options
  • Save RyuaNerin/3c23833b6a81aeb12352 to your computer and use it in GitHub Desktop.
Save RyuaNerin/3c23833b6a81aeb12352 to your computer and use it in GitHub Desktop.
비관리 메모리 관리 편하게 하려고 만든 클래스 https://ryuanerin.kr/post/2016-02-18-unmanaged-memory
// RyuaNerin
/* Usage
using 해서 사용하면 알아서 할당/해제를 해준다
Reallocate 해서 재할당 가능
IntPtr 인자 위치에 대신 사용가능함.
using (var mem = new UnmanagedMemory(4))
{
var toMem = BitConverter.BitConverter.GetBytes(0xF5769972);
Marshal.Copy(toMem, 0, mem, toMem.Length);
var fromMem = Marshal.ReadInt32(mem);
}
*/
public abstract class UnmanagedMemoryBase : IDisposable
{
public IntPtr Handle { get; protected set; }
public int Length { get; protected set; }
~UnmanagedMemoryBase()
{
this.Dispose(false);
}
private bool m_disposed = false;
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
protected void Dispose(bool disposing)
{
if (this.m_disposed) return;
this.m_disposed = true;
if (disposing)
this.Free();
}
protected virtual void Free()
{
if (this.Handle != IntPtr.Zero)
{
Marshal.FreeHGlobal(this.Handle);
this.Handle = IntPtr.Zero;
this.Length = -1;
}
}
public static implicit operator IntPtr(UnmanagedMemoryBase alloc)
{
return alloc.Handle;
}
}
public sealed class UnmanagedMemory : UnmanagedMemoryBase
{
public UnmanagedMemory(int size)
{
this.Reallocate(size);
}
public void Reallocate(int size)
{
if (size <= 0) throw new ArgumentOutOfRangeException();
this.Free();
try
{
this.Length = size;
this.Handle = Marshal.AllocHGlobal(this.Length);
var temp = new byte[this.Length];
Marshal.Copy(temp, 0, this.Handle, this.Length);
}
catch (Exception e)
{
this.Free();
throw e;
}
}
public UnmanagedMemory(byte[] array)
{
this.Reallocate(array);
}
public void Reallocate(byte[] array)
{
if (array == null || array.Length == 0) throw new ArgumentNullException();
this.Free();
try
{
this.Length = array.Length;
this.Handle = Marshal.AllocHGlobal(this.Length);
Marshal.Copy(array, 0, this.Handle, this.Length);
}
catch (Exception e)
{
this.Free();
throw e;
}
}
}
public sealed class UnmanagedStruct<T> : UnmanagedMemoryBase
where T: struct
{
public UnmanagedStruct()
{
this.Reallocate();
}
public UnmanagedStruct(T obj)
: this()
{
Marshal.StructureToPtr(obj, this.Handle, false);
}
public void Reallocate()
{
this.Free();
try
{
this.Length = Marshal.SizeOf(typeof(T));
this.Handle = Marshal.AllocHGlobal(this.Length);
var temp = new byte[this.Length];
Marshal.Copy(temp, 0, this.Handle, this.Length);
}
catch (Exception e)
{
this.Free();
throw e;
}
}
public void Reallocate(T obj)
{
this.Reallocate();
Marshal.StructureToPtr(obj, this.Handle, false);
}
public T PtrToStructure()
{
return (T)Marshal.PtrToStructure(this.Handle, typeof(T));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment