using CPF.Mac.ObjCRuntime; using System; using System.Runtime.InteropServices; namespace CPF.Mac.CoreFoundation { public class CFAllocator : INativeObject, IDisposable { private static CFAllocator Default_cf; private static CFAllocator SystemDefault_cf; private static CFAllocator Malloc_cf; private static CFAllocator MallocZone_cf; private static CFAllocator Null_cf; private static readonly IntPtr default_ptr; private static readonly IntPtr system_default_ptr; private static readonly IntPtr malloc_ptr; private static readonly IntPtr malloc_zone_ptr; internal static readonly IntPtr null_ptr; private IntPtr handle; public IntPtr Handle => handle; public static CFAllocator Default => Default_cf ?? (Default_cf = new CFAllocator(default_ptr)); public static CFAllocator SystemDefault => SystemDefault_cf ?? (SystemDefault_cf = new CFAllocator(system_default_ptr)); public static CFAllocator Malloc => Malloc_cf ?? (Malloc_cf = new CFAllocator(malloc_ptr)); public static CFAllocator MallocZone => MallocZone_cf ?? (MallocZone_cf = new CFAllocator(malloc_zone_ptr)); public static CFAllocator Null => Null_cf ?? (Null_cf = new CFAllocator(null_ptr)); static CFAllocator() { IntPtr intPtr = Dlfcn.dlopen("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", 0); try { default_ptr = Dlfcn.GetIntPtr(intPtr, "kCFAllocatorDefault"); system_default_ptr = Dlfcn.GetIntPtr(intPtr, "kCFAllocatorSystemDefault"); malloc_ptr = Dlfcn.GetIntPtr(intPtr, "kCFAllocatorMalloc"); malloc_zone_ptr = Dlfcn.GetIntPtr(intPtr, "kCFAllocatorMallocZone"); null_ptr = Dlfcn.GetIntPtr(intPtr, "kCFAllocatorNull"); } finally { Dlfcn.dlclose(intPtr); } } public CFAllocator(IntPtr handle) { this.handle = handle; } public CFAllocator(IntPtr handle, bool owns) { if (!owns) { CFObject.CFRetain(handle); } this.handle = handle; } ~CFAllocator() { Dispose(disposing: false); } public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (handle != IntPtr.Zero) { CFObject.CFRelease(handle); handle = IntPtr.Zero; } } [DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")] private static extern IntPtr CFAllocatorAllocate(IntPtr allocator, long size, CFAllocatorFlags hint); public IntPtr Allocate(long size, CFAllocatorFlags hint = (CFAllocatorFlags)0uL) { return CFAllocatorAllocate(handle, size, hint); } [DllImport("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation")] private static extern void CFAllocatorDeallocate(IntPtr allocator, IntPtr ptr); public void Deallocate(IntPtr ptr) { CFAllocatorDeallocate(handle, ptr); } } }