This question is derived from use of the CoreVideo framework but ultimately is about Swift types and interoperability with a C library. Hopefully others agree it's relevant enough for this forum.
In the CoreVideo APIs listed below, two very similar functions have slightly different Swift signatures that I don't understand. When used in Objective-C, both APIs take a pointer to a CVPixelBufferRef as their last parameter, but in Swift they take slightly different types.
Based on the old Create/Get ownership rules, both APIs vend a CVPixelBufferRef that the caller is responsible for deallocating so I'm not sure why the second API requires the additional use of Unmanaged whereas the first does not.
How do UnsafeMutablePointer<CVPixelBuffer?> and UnsafeMutablePointer<Unmanaged<CVPixelBuffer?>> differ in this case and why is one used over the other?
public func CVPixelBufferCreate(
_ allocator: CFAllocator?,
_ width: Int,
_ height: Int,
_ pixelFormatType: OSType,
_ pixelBufferAttributes: CFDictionary?,
_ pixelBufferOut: UnsafeMutablePointer<CVPixelBuffer?>
) -> CVReturn
public func CVPixelBufferCreateWithIOSurface(
_ allocator: CFAllocator?,
_ surface: IOSurfaceRef,
_ pixelBufferAttributes: CFDictionary?,
_ pixelBufferOut: UnsafeMutablePointer<Unmanaged<CVPixelBuffer>?>
) -> CVReturn
// This work as expected.
var allocatedPixelBuffer: CVPixelBuffer?
CVPixelBufferCreate(...., &allocatedPixelBuffer)
// This compiles:
var allocatedPixelBuffer: Unmanaged<CVPixelBuffer>?
CVPixelBufferCreateWithIOSurface(...., &allocatedSurfaceBuffer)
// But do I then call:
let pixelBuffer = allocatedPixelBuffer.takeRetained() // I assume this as `Create` rule applies?
let pixelBuffer = allocatedPixelBuffef.takeUnretained()
How do UnsafeMutablePointer<CVPixelBuffer?> and UnsafeMutablePointer<Unmanaged<CVPixelBuffer?>> differ in this case
I’ll come back to this below.
and why is one used over the other?
Because in the CVPixelBufferCreate case the parameter is decorated with CV_RETURNS_RETAINED_PARAMETER and in the CVPixelBufferCreateWithIOSurface case it’s not. Thus, Swift has no idea how to handle the memory management in the second case and that’s why it’s wrapped in an Unmanaged.
Based on the old Create/Get ownership rules, both APIs vend a CVPixelBufferRef that the caller is responsible for deallocating so
I'm not sure why the second API requires the additional use of
Unmanaged whereas the first does not.
The Create / Get rule applies to the function result, and in both of these cases the function result is of type CVReturn, which is not an object. Thus, the Create / Get rule doesn’t apply here.
As to how you handle this, in the second case you’ll need a takeRetained call to get you from unmanaged space into managed space. Personally I’d wrap it in something like this:
So the issue here is really just the lack of the decorator in the C interface? Otherwise the two functions are functionally the same when called from Swift, with the acknowledgement that .takeRetainedValue() is required because the decorator is missing.