2015-01-10 14 views
5

Ich verwende den dgeev Algorithmus aus der LAPACK-Implementierung im Accelerate-Framework, um Eigenvektoren und Eigenwerte einer Matrix zu berechnen. Leider sind die LAPACK-Funktionen nicht in der Apple-Dokumentation beschrieben, lediglich eine Verknüpfung zu http://netlib.org/lapack/faq.html ist enthalten.UnsafeMutablePointer <Int8> von String in Swift

Wenn Sie nachschlagen, werden Sie feststellen, dass die ersten beiden Argumente in dgeev Zeichen sind, die angeben, ob Eigenvektoren berechnet werden sollen oder nicht. In Swift wird nach UnsafeMutablePointer<Int8> gefragt. Wenn ich einfach "N" verwende, erhalte ich einen Fehler. Die dgeev Funktion und der Fehler sind im folgenden Screenshot beschrieben enter image description here

Was soll ich tun, um dies zu lösen?

Antwort

3

Das „Problem“ ist, dass die ersten beiden Parameter als char * und nicht als const char * deklariert werden, auch wenn die Saiten durch die Funktion nicht geändert werden:

int dgeev_(char *__jobvl, char *__jobvr, ...); 

zu Swift als

abgebildet wird
func dgeev_(__jobvl: UnsafeMutablePointer<Int8>, __jobvr: UnsafeMutablePointer<Int8>, ...) -> Int32; 

Eine mögliche Abhilfe ist

let result = "N".withCString { 
    dgeev_(UnsafeMutablePointer($0), UnsafeMutablePointer($0), &N, ...) 
} 

Innerhalb des Blocks ist $0 ein Zeiger auf ein NUL-terminiertes Array von char mit der UTF-8-Darstellung der Zeichenfolge.


Bemerkung:dgeev_() ändert nicht die durch die ersten beiden Argumente wies Strings, so als

int dgeev_(const char *__jobvl, const char *__jobvr, ...); 

erklärt "sollte", die als

zu Swift abgebildet werden würde
func dgeev_(__jobvl: UnsafePointer<Int8>, __jobvr: UnsafePointer<Int8>, ...) -> Int32; 

und in diesem Fall könnte man es einfach als

bezeichnen
let result = dgeev_("N", "N", &N, ...) 

weil Swift Strings automatisch zu UnsafePointer<Int8>) umgewandelt werden, wie in String value to UnsafePointer<UInt8> function parameter behavior erläutert.

3

Es ist hässlich, aber Sie verwenden können:

let unsafePointerOfN = ("N" as NSString).UTF8String 
var unsafeMutablePointerOfN: UnsafeMutablePointer<Int8> = UnsafeMutablePointer(unsafePointerOfN) 

und verwenden unsafeMutablePointerOfN als Parameter anstelle von "N".

+0

Es gibt zumindest ein theoretisches Problem mit dieser Lösung: Die von '.UTF8String' zurückgegebene Zeichenfolge ist nur solange gültig, wie das' NSString' Objekt existiert und das sofort zerstört werden kann, weil es keine Referenz darauf gibt es nach der ersten Zeile. Höchstwahrscheinlich wird dies hier nicht passieren, da die Zeichenkette hier eine Literalkonstante ist. –