Last active
April 5, 2016 23:41
-
-
Save RyuaNerin/3c23833b6a81aeb12352 to your computer and use it in GitHub Desktop.
비관리 메모리 관리 편하게 하려고 만든 클래스 https://ryuanerin.kr/post/2016-02-18-unmanaged-memory
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // 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