2016-09-02 1 views
0

Ich arbeite in einer FFI-Bibliothek und habe dieses Muster schon einige Male angetroffen, dass ich nicht weiß, wie man idiomatisch damit umgeht.Rust, FFI und Lebensdauer für String Transmutation

impl CanVoidStar for str { 
    fn as_cvoid_ptr(&self) -> *const c_void { 
     let string = CString::new(self).unwrap(); 
     unsafe { 
      return mem::transmute(string.as_ptr()); 
     } 
    } 
} 

Meine Absicht war es, einen const *void Zeiger auf ein Stück Erinnerung zu schaffen, die ich auf eine C-Funktion der Hand von kann. Das Problem, dass hier ist string geht aus dem Geltungsbereich und damit bekomme ich undefiniertes Verhalten im unsafe Block.

Gibt es eine Möglichkeit, die ich string auf dem Heap reserviert haben, bis was es ist, das den Rückgabewert damit getan wird? Gibt es einen idiomatischen Weg, um damit umzugehen, oder muss ich meine Algorithmen neu gestalten?

+0

http://jakegolding.com/rust-ffi-omnibus/ – Shepmaster

Antwort

4

Es sieht aus wie Sie die falsche Methode auf CString verwenden, und CString::into_raw() ist, was Sie wollen. Noch besser, es braucht keinen Code unsafe, bis Sie den Speicher wieder freigeben möchten.

Während CString::as_ptr() einen Zeiger in die Zeichenfolge zurückgibt, übergibt CString::into_raw() das Eigentum des Speichers in den rohen Zeiger; dies ist für genau Ihren Anwendungsfall bestimmt:

trait CanVoidStar { 
    fn as_cvoid_ptr(&self) -> *const c_void; 
} 

impl CanVoidStar for str { 
    fn as_cvoid_ptr(&self) -> *const c_void { 
     let string = CString::new(self).unwrap(); 
     string.into_raw() as *const c_void 
    } 
} 

Da die Dokumentation sagt, wenn Sie es jemals befreien wollen, werden Sie die CString mit CString::from_raw() rekonstruieren müssen, und dann haben sie wie üblich gesunken.

+0

Dies ist _exactly_ was ich brauchte und wie erwartet funktioniert. Danke Chris. – sholsapp

Verwandte Themen