Как перейти от CMutablePointer <CGFloat> к CGFloat [] в Swift
Я пытаюсь преобразовать класс ObjC, который использует Facebook pop library для Swift. Pop использует довольно немного C.
В ObjC у меня есть блок, который выглядит так...
prop.readBlock = ^(SHVGraphViewObjc *graphView, CGFloat values[]) {
values[0] = [graphView.centerOffsets[idx] doubleValue];
};
Эквивалентное определение закрытия в Свифте было бы
prop.readBlock = {(graphView: AnyObject!, values: CMutablePointer<CGFloat>) in }
Что я не могу понять, как преобразовать values[0] = [graphView.centerOffsets[idx] doubleValue];
в Swift? Как сообщить Swift, что CMutablePointer<CGFloat>
должен быть CGFloat[]
?
Ответы
Ответ 1
EDIT: просто хотел прояснить некоторые вещи, узнав немного больше из онлайн-документации (PDF).
В Swift существует несколько часто используемых типов указателей, вот как они сопоставляются с эквивалентами C:
Указатели как аргументы
CConstVoidPointer => const void *
CMutableVoidPointer => void *
CConstPointer<Type> => const Type *
CMutablePointer<Type> => Type *
Указатели как типы возврата, переменные и аргументы *
COpaquePointer => void *
UnsafePointer<Type> => Type *
ПРИМЕЧАНИЕ. Аргументы следуют этому правилу только, если они содержат более одного уровня указателя, в противном случае см. выше.
Указатели для типов классов
CConstPointer<Type> => Type * const *
CMutablePointer<Type> => Type * __strong *
AutoreleasingUnsafePointer<Type> => Type **
Стрелки Swift
При использовании указателя CConstPointer<Type>
в Swift вы можете передать любой из них:
-
nil
, который будет оцениваться как указатель NULL
- Значение A
CConstPointer<Type>
- A
CConstVoidPointer
значение
- A
CMutablePointer<Type>
значение
- A
CMutableVoidPointer
- A
AutoreleasingUnsafePointer<Type>
значение, которое при необходимости будет преобразовано в CConstPointer<Type>
- Значение A
Type
, переданное по адресу (&
operator)
- A
Type[]
массив
ПРИМЕЧАНИЕ. CConstVoidPointer
также может принимать любое из вышеуказанных значений.
При использовании указателя CMutablePointer<Type>
в Swift вы можете передать любой из них:
-
nil
, который будет оцениваться как указатель NULL
- A
CMutablePointer<Type>
значение
- Значение A
Type
, переданное по адресу (&
operator)
- A
Type[]
массив, переданный по адресу (&
operator)
ПРИМЕЧАНИЕ. CMutableVoidPointer
может принимать все вышеперечисленное в дополнение к значениям CMutableVoidPointer
.
Итак, в вашем случае, что CMutablePointer<CGFloat>
также может быть указателем на массив значений CGFloat
. Хотя я не совсем уверен, как разыгрывать это в Свифте. (Возможно, оператор as
?)
Ответ 2
В то время как ответ SiLo чрезвычайно детализирован, на конкретный вопрос здесь отвечают комментарии Росса под ним, поэтому я подумал, что я разберу их в полный ответ.
Мне нужно было сделать это недавно, чтобы взаимодействовать с моей инфраструктурой GPUImage через Swift. Для моего углового детектора Harris я использую блок обратного вызова для каждого обработанного кадра, который предоставляет массив C с плавающей запятой OpenGL в координатных парах X, Y вместе с размером этого массива попарно. Я использую массив C для производительности, так как это будет предоставлено 30-60 раз в секунду для видео в реальном времени. В Objective-C я бы установил это, используя следующий код:
UIImage *sourceImage = [UIImage imageNamed:@"ChairTest.png"];
GPUImageHarrisCornerDetector *cornerDetector = [[GPUImageHarrisCornerDetectionFilter alloc] init];
[cornerDetector setCornersDetectedBlock:^(GLfloat* cornerArray, NSUInteger cornersDetected, CMTime frameTime) {
NSLog(@"Number of corners detected: %d", cornersDetected);
NSLog(@"Corner 1, X: %f, Y: %f", cornerArray[0], cornerArray[1]);
}];
GPUImagePicture *inputPicture = [[GPUImagePicture alloc] initWithImage:sourceImage];
[inputPicture addTarget:cornerDetector];
[inputPicture processImage];
После того как я расшифровал правильный синтаксис закрытия, я не мог понять, как получить доступ к значениям входного массива C, где я передаю угловые координаты блоку обработки. Твиттер Шона Хебера об этом указывает на один из способов сделать это, что я использовал для перевода вышеуказанного Objective-C на следующий код Swift:
let sourceImage = UIImage(named: "ChairTest.png")
let cornerDetector = GPUImageHarrisCornerDetectionFilter()
cornerDetector.cornersDetectedBlock = { (cornerArray:CMutablePointer<GLfloat>, cornersDetected:Int, frameTime:CMTime) in
println("Number of corners detected: \(cornersDetected)")
let corners = UnsafePointer<GLfloat>(cornerArray)
println("Corner 1, X: \(corners[0]) Y: \(corners[1])")
}
let inputPicture = GPUImagePicture(image: sourceImage)
inputPicture.addTarget(cornerDetector)
inputPicture.processImage()
Это функционально идентично. Возможно, было бы безопаснее использовать .withUnsafePointer()
, но я не получил синтаксиса при этом.