Есть ли способ использовать команды Swift в низкоуровневом вызове метода C? - PullRequest
0 голосов
/ 11 марта 2020

Я поддерживаю набор данных, полученных из AVCaptureSynchronizedData. Один из методов, которые я использую, модифицирует CVPixelBuffers, полученный из AVCaptureSynchronizedData. Пока модифицирую. CVPixelBuffer, я создаю копию CVPixelBuffer через

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

На releaseCallBack ссылаются как

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

Однако я хотел бы иметь возможность сохранить с сколько раз это называется. Но, если я добавлю что-то вроде

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

, я получу ошибку

A C Указатель функции не может быть сформирован из замыкания, которое захватывает контекст

Не уверен, если это возможно, но было бы невероятно полезно иметь возможность подсчитывать количество разрушений указателя

1 Ответ

1 голос
/ 11 марта 2020

Ссылка на переменную экземпляра num в замыкании захватывает self, и это невозможно в обратном вызове, который является чистой C функцией.

Аналогично, как в Как использовать экземпляр Метод в качестве обратного вызова для функции, которая принимает только забавные c или буквальное замыкание . Вы должны использовать, чтобы пользовательский указатель (здесь: releaseRefCon) мог быть передан обратному вызову:

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)

Для Преобразования из указателя экземпляра (здесь: self) в указатель void и обратно в указатель экземпляра (здесь: mySelf) см. Как привести себя к UnsafeMutablePointer введите swift .

...