Член экземпляра x не может использоваться для типа y

Я пытался сделать обратный вызов сжатия, который отправляет сжатые данные в другую часть процесса, но когда я помещаю строку для отправки данных, я возвращаю эту ошибку

Член экземпляра «ptManager» не может использоваться для типа «SampleHandler».

Вот код обратного вызова:

let vtCallback : @convention(c) (UnsafeMutableRawPointer?, UnsafeMutableRawPointer?, OSStatus, VTEncodeInfoFlags, CMSampleBuffer?) -> Swift.Void =
    {
        (outputCallbackRefCon, sourceFrameRefCon, status, infoFlags, sampleBuffer) -> Swift.Void in
        
        let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer!)
        
        
        CVPixelBufferLockBaseAddress(imageBuffer!, CVPixelBufferLockFlags(rawValue: 0))
        CVPixelBufferLockBaseAddress(imageBuffer!, CVPixelBufferLockFlags(rawValue: 0))
        let bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer!)
        let height = CVPixelBufferGetHeight(imageBuffer!)
        let src_buff = CVPixelBufferGetBaseAddress(imageBuffer!)
        let data = NSData(bytes: src_buff, length: bytesPerRow * height)
        CVPixelBufferUnlockBaseAddress(imageBuffer!, CVPixelBufferLockFlags(rawValue: 0))
        
        NSLog("Size: " + String((data as Data).count))
        ptManager.sendObject(object: data, type: 102)
    }

Я просмотрел другие решения для этого, но не нашел ничего, что работало бы, потому что, если я установлю ptManager на static, это вызовет гораздо больше проблем, чем решит, и то же самое с удалением =.

Вся помощь в этом будет оценена!

Редактировать

Вот некоторые из более ранних кодов, которые я пробовал, которые могли работать, но никогда не вызывались, когда я назначал их обратному вызову:

func compressionOutputCallback(
    outputCallbackRefCon:UnsafeMutableRawPointer?,
    sourceFrameRefCon:UnsafeMutableRawPointer?,
    status:OSStatus,
    infoFlags:VTEncodeInfoFlags,
    sampleBuffer:CMSampleBuffer) {
     let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)
    CVPixelBufferLockBaseAddress(imageBuffer!, CVPixelBufferLockFlags(rawValue: 0))
    CVPixelBufferLockBaseAddress(imageBuffer!, CVPixelBufferLockFlags(rawValue: 0))
     let bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer!)
     let height = CVPixelBufferGetHeight(imageBuffer!)
     let src_buff = CVPixelBufferGetBaseAddress(imageBuffer!)
     let data = NSData(bytes: src_buff, length: bytesPerRow * height)
    CVPixelBufferUnlockBaseAddress(imageBuffer!, CVPixelBufferLockFlags(rawValue: 0))
    NSLog("Size: " + String((data as Data).count))
    ptManager.sendObject(object: data, type: 102)
     if status != noErr{
      NSLog("SBC: Error encoding video", status)
      print("SBC: Error encoding video", status)
       return
    }
    print("SBC: compressionOutputCallback dataBuffer", status)
  }
//Does not get called at all

Редактировать 2:

Вот где используется обратный вызов:

 VTCompressionSessionCreate(allocator: nil, width: 1080, height: 1920, codecType: kCMVideoCodecType_H264,encoderSpecification: nil, imageBufferAttributes: nil, compressedDataAllocator: nil, outputCallback: vtCallback as? VTCompressionOutputCallback, refcon: nil, compressionSessionOut: sessionOut)

person Z3R0    schedule 15.10.2020    source источник
comment
Это какое-то трудное место. Вы взаимодействуете с C API, который принимает указатель на функцию C (поэтому ваша функция или замыкание должны использовать @convention(c). Функции C в некотором смысле глобальны. Они не похожи на замыкания, которые размещаются в своей собственной памяти и может захватывать переменные Таким образом, функции C не могут получить доступ к неглобальным (или нестатическим) значениям, таким как ptManager, потому что негде хранить эту заключенную ссылку.   -  person Alexander    schedule 15.10.2020
comment
Точное решение для этого зависит от конкретного контекста, но обычно API-интерфейсы, которые принимают указатели на функции, также принимают что-то вроде void *userInfo. Этот указатель можно передать в вызов функции, а API передаст его в указатель функции обратного вызова в качестве одного из аргументов. Затем вы можете преобразовать этот void *userInfo в конкретный тип, который вы установили. Этот userInfo позволяет вам захватывать и передавать контекст, подобно тому, как замыкания автоматически заключают в себе переменные и дают вам доступ к ним. Не похоже, чтобы этот обратный вызов имел такой параметр, хотя.   -  person Alexander    schedule 15.10.2020
comment
Я думаю, что проблема со статической переменной, которую я могу обойти, заключается в том, что я должен объявить это ptManager = self позже, что вызывает проблемы. Я также разместил часть кода, который я пробовал ранее, но он вообще не вызывался на случай, если это поможет.   -  person Z3R0    schedule 15.10.2020
comment
Static — это всего лишь один из способов получить глобальную переменную. Это пространство имен, но по-прежнему по одному на программу, глобально доступное. Я бы не рекомендовал это. (Во-первых, что происходит, когда вам нужно несколько экземпляров, каждый со своим собственным ptManager? Вы должны показать контекст, где фактически используется vtCallback   -  person Alexander    schedule 15.10.2020
comment
В другом редактировании я добавил код, где используется vtCallback.   -  person Z3R0    schedule 15.10.2020
comment
@ Z3RO Параметр void *outputCallbackRefCon для VTCompressionSessionCreate - это именно тот механизм userInfo, о котором я говорил. VTCompressionSessionCreate примет это значение и передаст его в ваш обратный вызов как void *sourceFrameRefCon. Вы можете использовать это для контрабанды в любом контексте, например self или self.ptManager. Дайте мне знать, если дублированный вопрос не полностью отвечает на ваши вопросы.   -  person Alexander    schedule 15.10.2020
comment
Я пробовал это, но Unmanaged.passUnretained(self).toOpaque() выдает ошибку: Cannot invoke 'passUnretained' with an agrument list of type '((SampleHandler) -> () -> (SampleHandler))'.   -  person Z3R0    schedule 15.10.2020
comment
Давайте продолжим это обсуждение в чате.   -  person Alexander    schedule 15.10.2020