Подтвердить что ты не робот

Как перейти от 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[]?

4b9b3361

Ответ 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(), но я не получил синтаксиса при этом.