问题 如何从CMutablePointer 转到Swift中的CGFloat []


我正在尝试转换使用的ObjC类 Facebook的流行图书馆 到斯威夫特。 Pop使用相当多的C.

在ObjC中,我有一个看起来像这样的块...

prop.readBlock = ^(SHVGraphViewObjc *graphView, CGFloat values[]) {
                values[0] = [graphView.centerOffsets[idx] doubleValue];
            };

Swift中的等价闭包定义是

prop.readBlock = {(graphView: AnyObject!, values: CMutablePointer<CGFloat>) in }

我无法弄清楚的是如何转换 values[0] = [graphView.centerOffsets[idx] doubleValue]; 到斯威夫特?我如何让Swift知道这一点 CMutablePointer<CGFloat> 应该是一个 CGFloat[]


6705
2018-06-05 03:58


起源



答案:


编辑:只是想在从中学到更多东西之后澄清一些事情 在线文档(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 **

斯威夫特指针

使用时 CConstPointer<Type> 在Swift中的指针,您可以传递以下任何一个:

  • nil,将被评估为 NULL 指针
  • 一个 CConstPointer<Type> 值
  • 一个 CConstVoidPointer 值
  • 一个 CMutablePointer<Type> 值
  • 一个 CMutableVoidPointer
  • 一个 AutoreleasingUnsafePointer<Type> 将转换为的值 CConstPointer<Type> 如有必要
  • 一个 Type 地址传递的值(& 运营商)
  • 一个 Type[] 排列

注意:CConstVoidPointer 也可以采用上述任何一个值。

使用时 CMutablePointer<Type> 在Swift中的指针,您可以传递以下任何一个:

  • nil,将被评估为 NULL 指针
  • 一个 CMutablePointer<Type> 值
  • 一个 Type 地址传递的值(& 运营商)
  • 一个 Type[] 数组通过地址传递(& 运营商)

注意:CMutableVoidPointer 可以采取以上任何一种 CMUtableVoidPointer 值。

所以在你的情况下似乎是一个 CMutablePointer<CGFloat> 也可以是指向数组的指针 CGFloat 值。虽然我不完全确定如何在Swift中取消引用。 (也许是 as 操作?)


9
2018-06-05 07:16



在这种情况下,我没有打电话到街区。 Facebook的流行图书馆称之为。我需要知道的是如何使用 values 作为一个数组 GCFloats 从 内 块。 - Ross Kimes
我会说 CGFloat[]应该足够了,我确信Swift会将任何指针编组为数组(类似于C#,当插入C库时)。 - Erik
如果我将输入块更改为 CGFloat[] 从 CMutablePointer<CGFloat>, 它说 CMutablePointer<CGFloat> is not a subtype of CGFloat[]。 - Ross Kimes
也许保持你的 CMutablePointer<CGFloat> 原样。您可以使用 Array<CGFloat>.convertFromHeapArray(...) 并传入 RawPointer 和 owner 属性来自 CMutablePointer。不过,对于我来说,这在黑暗中有点像。 - Erik
我在这里找到了解决方案(twitter.com/BigZaphod/status/475137485602045952),但看起来你的最新编辑也涵盖了它。我最终做的是 let data = UnsafePointer<CGFloat>(values) data[0] = CGFloat(graphView.centerOffsets[index])。谢谢! - Ross Kimes


答案:


编辑:只是想在从中学到更多东西之后澄清一些事情 在线文档(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 **

斯威夫特指针

使用时 CConstPointer<Type> 在Swift中的指针,您可以传递以下任何一个:

  • nil,将被评估为 NULL 指针
  • 一个 CConstPointer<Type> 值
  • 一个 CConstVoidPointer 值
  • 一个 CMutablePointer<Type> 值
  • 一个 CMutableVoidPointer
  • 一个 AutoreleasingUnsafePointer<Type> 将转换为的值 CConstPointer<Type> 如有必要
  • 一个 Type 地址传递的值(& 运营商)
  • 一个 Type[] 排列

注意:CConstVoidPointer 也可以采用上述任何一个值。

使用时 CMutablePointer<Type> 在Swift中的指针,您可以传递以下任何一个:

  • nil,将被评估为 NULL 指针
  • 一个 CMutablePointer<Type> 值
  • 一个 Type 地址传递的值(& 运营商)
  • 一个 Type[] 数组通过地址传递(& 运营商)

注意:CMutableVoidPointer 可以采取以上任何一种 CMUtableVoidPointer 值。

所以在你的情况下似乎是一个 CMutablePointer<CGFloat> 也可以是指向数组的指针 CGFloat 值。虽然我不完全确定如何在Swift中取消引用。 (也许是 as 操作?)


9
2018-06-05 07:16



在这种情况下,我没有打电话到街区。 Facebook的流行图书馆称之为。我需要知道的是如何使用 values 作为一个数组 GCFloats 从 内 块。 - Ross Kimes
我会说 CGFloat[]应该足够了,我确信Swift会将任何指针编组为数组(类似于C#,当插入C库时)。 - Erik
如果我将输入块更改为 CGFloat[] 从 CMutablePointer<CGFloat>, 它说 CMutablePointer<CGFloat> is not a subtype of CGFloat[]。 - Ross Kimes
也许保持你的 CMutablePointer<CGFloat> 原样。您可以使用 Array<CGFloat>.convertFromHeapArray(...) 并传入 RawPointer 和 owner 属性来自 CMutablePointer。不过,对于我来说,这在黑暗中有点像。 - Erik
我在这里找到了解决方案(twitter.com/BigZaphod/status/475137485602045952),但看起来你的最新编辑也涵盖了它。我最终做的是 let data = UnsafePointer<CGFloat>(values) data[0] = CGFloat(graphView.centerOffsets[index])。谢谢! - Ross Kimes


虽然SiLo的回答非常详细,但罗斯在其下面的评论回答了这里的具体问题,所以我想我会将这些问题扩展为完整答案。

我最近需要这样做才能通过Swift与我的GPUImage框架连接。对于我的Harris角点检测器,我在每个处理过的帧上使用一个回调块,它提供X,Y坐标对中的OpenGL浮点值的C数组,以及成对的数组。我使用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数组的值,我将角坐标移交给处理块。 Sean Heber关于此的推文 指出了一种方法,我用它将上面的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(),但我还没有完全掌握语法。


3
2018-06-25 16:29