2017-02-21 6 views
1

Wie kann ich die folgende Zeigerinitialisierung von Swift 2 in Swift 3 konvertieren?Zeiger von Swift 2 in Swift konvertieren 3

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

Update: Vielen Dank für alle Antworten. Den Zeiger permanent neu binden, wie @Aderstedt vorschlägt funktioniert, aber das Ergebnis nicht zurückgibt. Irgendwelche Ideen?

// 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

Können Sie ein * eigenständiges * Beispiel zur Demonstration des Problems bereitstellen? Mit Eingabe, Ausgabe und erwarteter Ausgabe? –

+0

Danke @ martin-r !!! Ich möchte einen Herzfrequenzsensor mit der iOS-Kamera erstellen. Ich lese Bilder von der hinteren Kamera mit 30 fps und speichere den durchschnittlichen Farbton aus dem Bild in einem Array. Um Rauschen zu entfernen, möchte ich einen Bandpassfilter mit FFT und dem Accelerate-Framework erstellen. Ich teilte meinen Code in github https://github.com/codifilo/camera-heart-rate/blob/master/CameraHeartRate/FFT.swift#L119 – codifilo

+0

Was genau funktioniert nicht? - Bitte beachten Sie, dass Fragen zur Fehlersuche ("Warum funktioniert dieser Code nicht?") Das gewünschte Verhalten, ein spezifisches Problem oder einen Fehler und den kürzesten Code enthalten müssen, um ihn ** in der Frage selbst zu reproduzieren. ** Fragen ohne Eine klare Problemstellung ist für andere Leser nicht sinnvoll. Siehe auch: Erstellen eines [mcve]. –

Antwort

1

Sie müssen "rebind" den Zeiger:

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

     // ... 

    } 
} 

Im Inneren des Verschlusses valuesAsComplex ist ein UnsafeMutablePointer<DSPDoubleComplex> und kann an DSP Funktionen übergeben werden.

Sie müssen nicht passieren den Zeiger auf das Element Speicher zum außerhalb des Verschlusses als documentation eindeutig fest:

Der Zeiger Argument ist für die Dauer der Schließung der Ausführung gültig.

Das zufällig arbeiten kann, aber es gibt keine Garantie, dass die Speicherelemente noch am gleichen Speicheradresse ist (oder dass die Anordnung auch nach der Ausführung des Verschlusses vorhanden ist, da der Zeiger ist keine starke Referenz, die die Lebensdauer des Speichers gewährleistet).


In Ihrem Fall, die

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); 

und

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

Es funktioniert. Vielen Dank für Ihre Zeit. – codifilo

-2

Neben Martin R Antwort sein würde, in dem Sie den Inhalt von values als DSPDoubleComplex im nicht zugreifen können Ausschließende Schließung, Sie können den Speicher auch dauerhaft an einen neuen Typ wie diesen neu binden:

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

Der Zeiger, der an den Abschluss aller 'withUnsafe ....' Methoden übergeben wird, ist nur für die Dauer der Ausführung des Abschlusses gültig. Siehe zum Beispiel die Warnung in https://developer.apple.com/reference/foundation/data/1779823-withunsafemutablebytes. Soweit ich es verstehe, erweitert bindMemory nicht die Gültigkeit des Zeigers. –

+0

Im obigen Beispiel können Sie außerhalb des Abschlusses auf "valuesAsComplex" zugreifen (und mutieren). Die Dokumentation für 'bindMemory' wird jedoch mit einem großen roten Warnzeichen angezeigt, daher bin ich mir nicht sicher, ob dieser Ansatz allgemein verwendet werden soll. – Aderstedt

+0

Der obige Link war falsch. Was ich meinte, ist https://developer.apple.com/reference/swift/array/1538652-withunsafemutablebufferpointer: * "Das Zeigerargument ist nur für die Dauer der Ausführung der Schließung gültig." * –

Verwandte Themen