Creating a Custom CFType Type

Is it possible to create opaque types not derived from CFTypeRef that can be saved / freed using CFRetain / CFRelease ? Or how can I get a new type from CFType ?

+4
source share
2 answers

CoreFoundation itself does not provide such a mechanism, but all Cocoa objects will work with CFRetain and CFRelease. Thus, the only supported answer: create a class based on Foundation and CoreFoundation will recognize it as CFTypeRef.

+4
source

I have never done this, but you can use a private API. In all likelihood, it will depend on a specific point version of OS X, as CF runtimes may vary from release to release. In any case, CF is open source, so I looked at what CFRuntime does. I was glad to see that Apple included an example:

 // ========================= EXAMPLE ========================= // Example: EXRange -- a "range" object, which keeps the starting // location and length of the range. ("EX" as in "EXample"). // ---- API ---- typedef const struct __EXRange * EXRangeRef; CFTypeID EXRangeGetTypeID(void); EXRangeRef EXRangeCreate(CFAllocatorRef allocator, uint32_t location, uint32_t length); uint32_t EXRangeGetLocation(EXRangeRef rangeref); uint32_t EXRangeGetLength(EXRangeRef rangeref); // ---- implementation ---- #include <CoreFoundation/CFBase.h> #include <CoreFoundation/CFString.h> struct __EXRange { CFRuntimeBase _base; uint32_t _location; uint32_t _length; }; static Boolean __EXRangeEqual(CFTypeRef cf1, CFTypeRef cf2) { EXRangeRef rangeref1 = (EXRangeRef)cf1; EXRangeRef rangeref2 = (EXRangeRef)cf2; if (rangeref1->_location != rangeref2->_location) return false; if (rangeref1->_length != rangeref2->_length) return false; return true; } static CFHashCode __EXRangeHash(CFTypeRef cf) { EXRangeRef rangeref = (EXRangeRef)cf; return (CFHashCode)(rangeref->_location + rangeref->_length); } static CFStringRef __EXRangeCopyFormattingDesc(CFTypeRef cf, CFDictionaryRef formatOpts) { EXRangeRef rangeref = (EXRangeRef)cf; return CFStringCreateWithFormat(CFGetAllocator(rangeref), formatOpts, CFSTR("[%u, %u)"), rangeref->_location, rangeref->_location + rangeref->_length); } static CFStringRef __EXRangeCopyDebugDesc(CFTypeRef cf) { EXRangeRef rangeref = (EXRangeRef)cf; return CFStringCreateWithFormat(CFGetAllocator(rangeref), NULL, CFSTR("<EXRange %p [%p]>{loc = %u, len = %u}"), rangeref, CFGetAllocator(rangeref), rangeref->_location, rangeref->_length); } static void __EXRangeEXRangeFinalize(CFTypeRef cf) { EXRangeRef rangeref = (EXRangeRef)cf; // nothing to finalize } static CFTypeID _kEXRangeID = _kCFRuntimeNotATypeID; static CFRuntimeClass _kEXRangeClass = {0}; /* Something external to this file is assumed to call this * before the EXRange class is used. */ void __EXRangeClassInitialize(void) { _kEXRangeClass.version = 0; _kEXRangeClass.className = "EXRange"; _kEXRangeClass.init = NULL; _kEXRangeClass.copy = NULL; _kEXRangeClass.finalize = __EXRangeEXRangeFinalize; _kEXRangeClass.equal = __EXRangeEqual; _kEXRangeClass.hash = __EXRangeHash; _kEXRangeClass.copyFormattingDesc = __EXRangeCopyFormattingDesc; _kEXRangeClass.copyDebugDesc = __EXRangeCopyDebugDesc; _kEXRangeID = _CFRuntimeRegisterClass((const CFRuntimeClass * const)&_kEXRangeClass); } CFTypeID EXRangeGetTypeID(void) { return _kEXRangeID; } EXRangeRef EXRangeCreate(CFAllocatorRef allocator, uint32_t location, uint32_t length) { struct __EXRange *newrange; uint32_t extra = sizeof(struct __EXRange) - sizeof(CFRuntimeBase); newrange = (struct __EXRange *)_CFRuntimeCreateInstance(allocator, _kEXRangeID, extra, NULL); if (NULL == newrange) { return NULL; } newrange->_location = location; newrange->_length = length; return (EXRangeRef)newrange; } uint32_t EXRangeGetLocation(EXRangeRef rangeref) { return rangeref->_location; } uint32_t EXRangeGetLength(EXRangeRef rangeref) { return rangeref->_length; } #endif 
+7
source

Source: https://habr.com/ru/post/1333498/


All Articles