I am trying to convert an ObjC class that uses Facebook\'s pop library to Swift. Pop uses quite a bit of C.
In ObjC, I have a block that looks like this...
While SiLo's answer is extremely detailed, the specific question here is answered by Ross' comments underneath it, so I thought I'd expand those into a full answer.
I needed to do this recently in order to interface with my GPUImage framework via Swift. For my Harris corner detector, I use a callback block on each processed frame that provides a C array of OpenGL floating-point values in X, Y coordinate pairs, along with the size of that array in pairs. I use a C array for performance, since this will be provided 30-60 times per second on live video. In Objective-C, I would set this up using code like the following:
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];
After I deciphered the proper closure syntax, I couldn't quite figure out how to access the values of the input C array where I hand over corner coordinates to the processing block. Sean Heber's tweet about this points out one way to do this, which I used to translate the above Objective-C to the following Swift code:
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()
This appears to be functionally identical. It might be safer to use .withUnsafePointer()
, but I haven't quite gotten the syntax on that down.
EDIT: Just wanted to clarify a few things after learning a bit more from the online documentation (PDF).
There are a few commonly used pointer types in Swift, here is how they map to C equivalents:
CConstVoidPointer => const void *
CMutableVoidPointer => void *
CConstPointer<Type> => const Type *
CMutablePointer<Type> => Type *
COpaquePointer => void *
UnsafePointer<Type> => Type *
NOTE: Arguments follow this rule only when they are more than one pointer level deep, otherwise see above.
CConstPointer<Type> => Type * const *
CMutablePointer<Type> => Type * __strong *
AutoreleasingUnsafePointer<Type> => Type **
When using the CConstPointer<Type>
pointer in Swift, you may pass any one of these:
nil
, which will be evaluated as a NULL
pointerCConstPointer<Type>
valueCConstVoidPointer
valueCMutablePointer<Type>
valueCMutableVoidPointer
AutoreleasingUnsafePointer<Type>
value which will be converted to CConstPointer<Type>
if necessaryType
value passed by address (&
operator)Type[]
arrayNOTE:CConstVoidPointer
can take any of the above values as well.
When using the CMutablePointer<Type>
pointer in Swift, you may pass any one of these:
nil
, which will be evaluated as a NULL
pointerCMutablePointer<Type>
valueType
value passed by address (&
operator)Type[]
array passed by address (&
operator) NOTE:CMutableVoidPointer
can take any of the above in addition to CMUtableVoidPointer
values.
So it would seem in your case that a CMutablePointer<CGFloat>
could also be a pointer to an array of CGFloat
values. Though I am not completely sure how to dereference that in Swift. (Perhaps the as
operator?)