2017-02-21 73 views
1

如何将以下指针从Swift 2初始化为Swift 3?将指针从Swift 2转换为Swift 3

var values: [Double] 
... 
var valuesAsComplex : UnsafeMutablePointer<DSPDoubleComplex>? 
values.withUnsafeBufferPointer { (resultPointer: UnsafeBufferPointer<Double>) -> Void in 
    valuesAsComplex = UnsafeMutablePointer<DSPDoubleComplex>(resultPointer.baseAddress) 
} 

更新: 感谢您的所有答案。 将@Aderstedt指针永久重新绑定指示工作,但返回结果不会。有任何想法吗?

// Create result 
var result = [Double](repeating: 0.0, count: N/2) 
var resultAsComplex : UnsafeMutablePointer<DSPDoubleComplex>? 
result.withUnsafeMutableBytes { 
    resultAsComplex = $0.baseAddress?.bindMemory(to: DSPDoubleComplex.self, capacity: result.count) 
} 

// Do complex->real inverse FFT. 
vDSP_fft_zripD(fftSetup!, &tempSplitComplex, 1, LOG_N, FFTDirection(FFT_INVERSE)); 

// This leaves result in packed format. Here we unpack it into a real vector. 
vDSP_ztocD(&tempSplitComplex, 1, resultAsComplex!, 2, N2); 

// Neither the forward nor inverse FFT does any scaling. Here we compensate for that. 
var scale : Double = 0.5/Double(N); 
vDSP_vsmulD(&result, 1, &scale, &result, 1, vDSP_Length(N)); 

return result 
+0

您能否提供一个*自包含的*示例来说明问题?有了投入,产出和预期产出? –

+0

谢谢@ martin-r !!!我想创建一个使用iOS相机的心率监视器。我正在以30fps的速度读取后置摄像头的图像,并将图像的平均色调存储在一个阵列中,为了去除噪声,我想使用FFT和Accelerate框架创建一个带通滤波器。 我在github中分享了我的代码https://github.com/codifilo/camera-heart-rate/blob/master/CameraHeartRate/FFT.swift#L119 – codifilo

+0

究竟哪些方法无效? - 请注意,寻求调试帮助的问题(“为什么这个代码不工作?”)必须包含所需的行为,特定的问题或错误以及在问题本身中重现**的最短代码。一个明确的问题陈述对其他读者没有用处。另请参阅:如何创建[mcve]。 –

回答

1

你必须 “重新绑定” 指针:

values.withUnsafeMutableBufferPointer { 
    $0.baseAddress!.withMemoryRebound(to: DSPDoubleComplex.self, capacity: values.count/2) { 
     valuesAsComplex in 

     // ... 

    } 
} 

关闭valuesAsComplex里面是一个 UnsafeMutablePointer<DSPDoubleComplex>并且可以传递给DSP 功能。

您必须指针传递到元素存储到 外界封闭的documentation的明确规定:

的指针参数只适用于封闭的执行期间。

这可能是偶然的工作,但也不能保证该 执行封盖后,元件存储还是在同一 存储器地址(或该数组即使存在,由于指针 是不是确保存储寿命的强有力参考)。


在你的情况,这将是

tempSplitComplex = DSPDoubleSplitComplex(realp: &mag, imagp: &phase) 
    vDSP_ztocD(&tempSplitComplex, 1, &tempComplex, 2, N2); 

    tempComplex.withUnsafeMutableBufferPointer { 
     $0.baseAddress!.withMemoryRebound(to: Double.self, capacity: values.count * 2) { 
      complexAsDouble in 

      vDSP_rectD(complexAsDouble, 2, complexAsDouble, 2, N2); 
     } 
    } 

    vDSP_ctozD(&tempComplex, 2, &tempSplitComplex, 1, N2); 

var result = [Double](repeating: 0.0, count: N/2) 

    result.withUnsafeMutableBufferPointer { 
     $0.baseAddress!.withMemoryRebound(to: DSPDoubleComplex.self, capacity: result.count/2) { 
      resultAsComplex in 

      vDSP_ztocD(&tempSplitComplex, 1, resultAsComplex, 2, N2); 

     } 
    } 
+0

它的工作原理。感谢您的时间。 – codifilo

-2

除了马丁的r的回答,您可以在其中内非访问values内容作为DSPDoubleComplex逃避关闭,你也可以永久性地将内存重新绑定到这样的新类型:

var values: [Double] = ... 

var valuesAsComplex : UnsafeMutablePointer<DSPDoubleComplex>? = nil 

values.withUnsafeMutableBytes { 
    valuesAsComplex = $0.baseAddress?.bindMemory(to: DSPDoubleComplex.self, capacity: values.count) 
} 

// You can access valuesAsComplex here: 
print("\(valuesAsComplex![0].real)") 

// ... and mutate it. 
valuesAsComplex![0].imag = 1 
+0

传递给所有'withUnsafe ....'方法的闭包的指针仅在闭包执行期间有效。例如,请参阅https://developer.apple.com/reference/foundation/data/1779823-withunsafemutablebytes中的警告。据我所知,bindMemory不会扩展指针的有效性。 –

+0

在上面的示例中,您可以在闭包之外访问(并变异)'valuesAsComplex'。虽然'bindMemory'的文档带有一个很大的红色警告标志,所以我不确定这种方法是否应该用于一般情况。 – Aderstedt

+0

上面的链接是错误的。我的意思是https://developer.apple.com/reference/swift/array/1538652-withunsafemutablebufferpointer:*“指针参数只对封闭执行期间有效。”* –