2015-05-05 4 views
10

Ho una funzione C mappata Swift definito come:stringa convertire Swift per UnsafeMutablePointer <Int8>

func swe_set_eph_path(path: UnsafeMutablePointer<Int8>) -> Void 

Sto cercando di passare un percorso alla funzione e hanno provato:

 var path = [Int8](count: 1024, repeatedValue: 0); 
     for i in 0...NSBundle.mainBundle().bundlePath.lengthOfBytesUsingEncoding(NSUTF16StringEncoding)-1 
     { 
      var range = i..<i+1 
      path[i] = String.toInt(NSBundle.mainBundle().bundlePath[range]) 
     } 
     println("\(path)") 
     swe_set_ephe_path(&path) 

ma la linea del percorso [i] ottengo l'errore:

'subscript' is unavailable: cannot subscript String with a range of Int

swe_set_ephe_path(NSBundle.mainBundle().bundlePath) 

swe_set_ephe_path(&NSBundle.mainBundle().bundlePath) 

non funzionano né

Oltre a non lavorare, mi sento ci deve essere un modo migliore, meno contorto di fare questo. Le risposte precedenti su StackOverflow con CString non sembrano più funzionare. Eventuali suggerimenti?

+0

prega, quando mostra il codice, mostrano sempre _real_ codice. La tua dichiarazione non è reale - non è una dichiarazione di funzione Swift valida e sospetto che il nome della funzione sia sbagliato. Non digitare il codice in Stack Overflow; copia e incolla il codice _real_. Sempre. – matt

risposta

15

Previous answers on StackOverflow using CString don't seem to work anymore

Tuttavia, UnsafePointer<Int8> è una stringa C. Se il contesto richiede assolutamente un UnsafeMutablePointer, proprio costringere, in questo modo:

let s = NSBundle.mainBundle().bundlePath 
let cs = (s as NSString).UTF8String 
var buffer = UnsafeMutablePointer<Int8>(cs) 
swe_set_ephe_path(buffer) 

Certo che non ho il tuo swe_set_ephe_path, ma funziona bene nel mio test, quando si spense in questo modo:

+0

Sembrava funzionare alla grande. Utilizza aspetti di Swift che non avevo familiarità con, quindi per la risposta alla domanda e una lezione sugli aspetti linguistici più avanzati, è un vincitore su entrambi i punti. Grazie! – SteveFerg

+0

Felice di aiutare. Tutto è uscito direttamente dal mio libro, qui: http://www.apeth.com/swiftBook/apa.html#_c_data_types Fammi sapere che hai altre domande su cosa fa il codice. – matt

+0

Dannazione! Ho appena comprato e letto quel libro ma non ho guardato l'appendice! Lo farò ora ... – SteveFerg

6

In realtà è estremamente irritante per la libreria che si sta utilizzando che richiede (nella dichiarazione C) uno char * path anziché const char * path. (questo presuppone che la funzione non muti la stringa di input - se lo fa, ci si trova in una situazione completamente diversa).

Se non lo fa, la funzione sarebbe venire a Swift come:

// note, UnsafePointer not UnsafeMutablePointer 
func swe_set_eph_path(path: UnsafePointer<Int8>) -> Void 

e si potrebbe quindi fare affidamento sulla conversione implicita di Swift:

let str = "blah" 
swe_set_eph_path(str) // Swift implicitly converts Strings 
         // to const C strings when calling C funcs 

ma si può fare una conversione non sicuro abbastanza facilmente, in combinazione con la funzione withCString:

str.withCString { cstr in 
    swe_set_eph_path(UnsafeMutablePointer(cstr)) 
} 
+0

Sì, stavo pensando di mostrargli 'withCString' come un'alternativa Swiftier a' (s come NSString) .UTF8String' - In realtà l'ho inserito, e poi l'ho estratto di nuovo. :) - Non ho idea del motivo per cui ha bisogno di un puntatore mutabile non sicuro; L'ho appena dato perché ha detto che ne aveva bisogno. – matt

+0

A parte il fatto che è pure-Swiftness, preferisco 'withCString' perché rende esplicito lo scope. Sono molto nervoso per questo '(str come NSString) .UTF8String'. Quando viene distrutta la versione 'NSString', presumibilmente portando con sé la memoria assegnata alla versione UTF-8? Non è chiaro. Forse prima che tu abbia la possibilità di usarlo ... –

+0

In realtà non è mai stato assegnato. È solo un modo di guardare la stringa originale. Confido che il compilatore non ottimizzi la stringa originale! Forse non dovrei. – matt

5

ho avuto una libreria statica (someLibrary.a) scritta in C++ compilata per iOS. Il file di intestazione (someLibrary.h) ha avuto una funzione esposta come questo:

extern long someFunction(char* aString);

La dichiarazione di Swift si presenta così:

Int someFunction(aString: UnsafeMutablePointer<Int8>)

ho fatto una proroga per String:

extension String { 
    var UTF8CString: UnsafeMutablePointer<Int8> { 
     return UnsafeMutablePointer((self as NSString).UTF8String) 
    } 
} 

Quindi posso chiamare la metanfetamina od in questo modo:

someFunction(mySwiftString.UTF8CString)