2014-12-31 13 views
5

Sto lavorando con API di terze parti c Sto cercando di chiamare una delle funzioni con una stringa semplice. Qualcosa di simile a questo:Converti stringa in UnsafeMutablePointer <char_t> in Swift

some_c_func("aString"); 

ottengo un errore di generazione:

Type 'UnsafeMutablePointer<char_t>' does not conform to protocol 'StringLiteralConvertible' 

Ho visto alcuni suggerimenti per utilizzare utf8 su stringa o conversioni simili, che ottiene quasi arrivati, ma con il seguente errore:

some_c_func("aString".cStringUsingEncoding(NSUTF8StringEncoding)); 
'UnsafePointer<Int8>' is not convertible to 'UnsafeMutablePointer<char_t>' 

Come posso creare un UnsafeMutablePointer?

risposta

1

Tutto dipende da cosa è char_t.

Se char_t viene convertito in Int8, funzionerà quanto segue.

if let cString = str.cStringUsingEncoding(NSUTF8StringEncoding) { 
    some_c_func(strdup(cString)) 
} 

Questo può essere crollato a

some_c_func(strdup(str.cStringUsingEncoding(NSUTF8StringEncoding)!)) 

ATTENZIONE! Questo secondo metodo causerà un arresto anomalo se func cStringUsingEncoding(_:) restituisce nil.


Aggiornamento per Swift 3, e per risolvere la perdita di memoria

Se la stringa C è necessaria solo in un ambito locale, poi non strdup() è necessario.

guard let cString = str.cString(using: .utf8) else { 
    return 
} 

some_c_func(cString) 

cString avrà lo stesso ciclo di vita memoria, come str (pure simile almeno).

Se la stringa C deve vivere al di fuori dell'ambito locale, sarà necessaria una copia. Quella copia dovrà essere liberata.

guard let interimString = str.cString(using: .utf8), let cString = strdup(interimString) else { 
    return 
} 

some_c_func(cString) 

//… 

free(cString) 
+0

Funziona, grazie! Ma non lo fa (non è più?) Richiede lo srotolamento opzionale. La firma su cStringUsingEncoding è 'func cStringUsingEncoding (encoding: UInt) -> UnsafePointer ' e strdup la converte in UnsafeMutablePointer. – brodney

+0

@brodney heh, sto usando gli strumenti Xcode 6.1.1 (6A2008a): la firma è 'func cStringUsingEncoding (encoding: NSStringEncoding) -> [CChar]?' Quale downgrade a 'UnsafePointer ?' –

+0

Usando strdup, si devi liberare il buffer. defer {free (cString)} –

0

non hanno provato stringhe come quella di passaggio, ma ho una funzione C che chiamo da Swift, che richiede molto più parametri qui illustrato, tra i quali è un riferimento ad un buffer di typecast Swift C per contenere una stringa di errore. Il compilatore non si lamenta e la chiamata alla funzione funziona. Spero che questo ti porti più vicino alla risposta e puoi fornire un aggiornamento con la risposta finale o qualcun altro può farlo.

var err = [CChar](count: 256, repeatedValue: 0) 
    var rv = somefunc((UnsafeMutablePointer<Int8>)(err)) 

    if (rv < 0) { 
     println("Error \(err)") 
     return 
    } 
1

può essere più semplice di quello - molte API C passano le stringhe in giro come char * tipi, e tratta rapidi questi come non sicuri.

provare ad aggiornare l'API C (buona) o modificare i suoi file di intestazione (non validi) per dichiararli come const char *.

nella mia esperienza questo consente di passare tipi di stringhe swift standard direttamente all'API C.

a quanto pare è necessaria una costante, per conformarsi al protocollo.

+0

Eccellente! Mi aiuti molto con questo. Ho perso molti contesti a causa della conversione da String a UnsafeMutablePointer e viceversa. strdup sembra così sporco in fretta, e non facile da dealloc (e dove dealloc). TK –