2017-06-05 8 views
1

in c-Datei: eine StrukturC Struct zu Swift

struct CPerson { 
    const char* name; 
    int age; 
}; 

in schnellen Datei:

extension UnsafePointer where Pointee == Int8 { 
    var string : String? { 
    return String.init(cString: self) 
    } 
} 

I Verwendung c struct versuchen:

print(CPerson(name: "baby", age: 1).name.string) 
//Optional("baby") 

aber:

let p = CPerson(name: "angela", age: 1) 
print(p.name.string , p.age) 
//Optional("") 1 

Warum p.name.string == ""?

hoffe ich, dass p.name.string == "angela"

Dank.

+0

Müssen Sie mit C struct (s) arbeiten? Warum implementiert man es nicht einfach mit Swift? –

Antwort

1

Es ist ein Speicherverwaltungsproblem. In

let p = CPerson(name: "angela", age: 1) 

geben Sie einen Swift String auf eine Funktion eines UnsafePointer<Int8> Argument (das Äquivalent von Swift const char *) nehmen. Der Compiler fügt Code ein, um eine temporäre C-Zeichenfolgedarstellung zu erstellen, und übergibt das an den Initialisierer CPerson. Das Feld name zeigt dann auf diese temporäre C-Zeichenfolge.

Das Problem ist, dass dieser Zeiger nicht mehr gültig ist, wenn der Initialisierer zurückgibt. Es kann auf etwas anderes hinweisen oder ein ungültiger Zeiger sein.

Ein const char * in C ist nur ein Zeiger, es impliziert keine Besitz oder Speicherverwaltung. Sie würden genau die gleiche Problem in C, wenn Sie

person.name = someString; 

zuweisen und den Umfang verlassen, wo someString definiert ist.

Sie müssen also entscheiden, wer verantwortlich ist zu reservieren (und frei) die C-String-Speicher.

Eine Möglichkeit wäre, die Zeichenfolge in Swift zu duplizieren und Release den Speicher, wenn es nicht mehr benötigt wird:

let name = strdup("angela") 

let p = CPerson.init(name: name, age: 1) 
print(p.name.string , p.age) // Optional("angela") 1 

free(name) 

Eine weitere Option könnte C-Funktionen CreatePerson() und ReleasePerson() zu schaffen sein, das zuweisen und frei Lager.

+0

danke! perfekt ! – Xiuye