2017-02-21 62 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:*「指針參數只對封閉執行期間有效。」* –