0

I am maintaining a set of data obtained from a AVCaptureSynchronizedData. One of the methods I use modifies the CVPixelBuffers obtained from the AVCaptureSynchronizedData. While modifying. the CVPixelBuffer, I create a copy of the CVPixelBuffer via

let status = CVPixelBufferCreateWithBytes(nil, scaleWidth, scaleHeight,
                                                  pixelFormat, destData,
                                                  destBytesPerRow, releaseCallback,
                                                  nil, nil, &dstPixelBuffer)

The releaseCallBack is referenced as

let releaseCallback: CVPixelBufferReleaseBytesCallback = { _, ptr in
    if let ptr = ptr {
        free(UnsafeMutableRawPointer(mutating: ptr))
    }
}

However, I would like to be able to keep up with how many times this is called. But, if I add something like

var num:Int = 0
let releaseCallback: CVPixelBufferReleaseBytesCallback = { _, ptr in
    if let ptr = ptr {
        num += 1
        free(UnsafeMutableRawPointer(mutating: ptr))
    }
}

I get the error

A C function pointer cannot be formed from a closure that captures context

Not sure if it is possible, but it would be incredibly useful to be able to keep count of the number of times a pointer is destroyed

impression7vx
  • 1,728
  • 1
  • 20
  • 50
  • Possibly helpful: https://stackoverflow.com/a/33262376/1187415. – The problem is (as I assume) that `num` is an instance variable, so that the closure actually captures `self`. – Martin R Mar 11 '20 at 06:45
  • Correct. It is implicitly self.num – impression7vx Mar 11 '20 at 14:09
  • Problem is, I cannot change the callback type as it is strictly a type created in Swift. It is looking for that specific callback. I believe the other solutions modifies it a little – impression7vx Mar 11 '20 at 14:11

1 Answers1

1

Referencing the instance variable num in the closure captures self and that is not possible in the callback which is a pure C function.

Similarly as in How to use instance method as callback for function which takes only func or literal closure you have to use that a custom pointer (here: releaseRefCon) can be passed to the callback:

let releaseCallback: CVPixelBufferReleaseBytesCallback = { releaseRefCon, ptr in
    let mySelf = Unmanaged<YourClass>.fromOpaque(releaseRefCon!).takeUnretainedValue()
    if let ptr = ptr {
        free(UnsafeMutableRawPointer(mutating: ptr))
        mySelf.num += 1
    }
}

let releaseRefCon = UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque())
let status = CVPixelBufferCreateWithBytes(nil, scaleWidth, scaleHeight,
                                          pixelFormat, destData,
                                          destBytesPerRow,
                                          releaseCallback, releaseRefCon,
                                          nil, &dstPixelBuffer)

For the conversions from an instance pointer (here: self) to a void pointer and back to an instance pointer (here: mySelf) see How to cast self to UnsafeMutablePointer<Void> type in swift.

Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • Ahh I see. I saw the paramater releaseRefCon and I knew it was for instance variables but wasn’t sure on how yo create a UnsafeMutableRawPointer that allowed me to obtain a reference to self or anything else. Thanks so much! – impression7vx Mar 11 '20 at 18:42
  • I’ll test it out here shortly and give ya the check assuming all goes well – impression7vx Mar 11 '20 at 18:42