2017-03-10 5 views
2

Ich schreibe eine sichere Rust-Schicht, mit der ich Funktionen aus einer C-Bibliothek in Rust aufrufen kann. Ich habe die unsicheren Bindungen mit rust-bindgen generiert, aber ich bin ein wenig verwirrt über die Unterschiede zwischen Rust und C in Bezug auf die Weitergabe von Zeigern.Übergeben einer Rust-Variablen an eine C-Funktion, die in der Lage ist, sie zu ändern

Die C-Funktion sieht wie folgt aus:

bool imeGet(unsigned char address, int *value); 

Es liest einen I2C Sensor an address, speichert das Ergebnis in value und gibt TRUE auf Erfolg.

Bindgen hat die Rust-Funktion wie folgt aussehen:

pub fn imeGet(address: ::std::os::raw::c_uchar, 
       value: *mut ::std::os::raw::c_int) -> bool; 

Und meine sichere Anrufer sieht wie folgt zur Zeit:

pub fn ime_get(addr: u8) -> i32 { 
    let v: &mut i32 = 0; 
    unsafe { 
     imeGet(addr, v); 
     *v 
    } 
} 

Dieser Code kompiliert nicht wegen der = 0. Wenn ich das nicht hatte, beschwerte sich der Compiler über v möglicherweise nicht initialisiert worden. Meine Absicht ist, den Erfolg innerhalb dieser Funktion zu behandeln, und nur den i32 Wert zurückzugeben.

Wie gehe ich mit dem Verhalten des *mut c_int Arguments um? Ich habe versucht, v als eine Referenz zu deklarieren und seinen dereferenzierten Wert (oben) zurückgeben, aber das funktioniert nicht. Ich habe auch versucht, nur v zurückgeben, aber ich möchte nicht wirklich den Rückgabewert veränderbar bleiben.

Ich bin ziemlich neu in Rust, aber ich habe einen ordentlichen Hintergrund in C, was meine Quelle der Verwirrung sein kann.

Antwort

4

aber ich habe einen anständigen Hintergrund in C

Die moralische Äquivalent des Rust-Code ist:

int *v = NULL; 
imeGet(addr, v); 
*v 

Dies wird einen Fehler, weil der C-Code wahrscheinlich wird sich dereferenz, dass v den Wert zu speichern, außer Sie haben in einem NULL übergeben, so ist es wahrscheinlicher, Boom zu gehen.

Sie müssen Speicher für den Wert zu schaffen, bieten dann einen Verweis auf diese Speicher auf die Funktion:

fn ime_get(addr: u8) -> i32 { 
    let mut v = 0; 
    unsafe { imeGet(addr, &mut v) }; 
    v 
} 

Für Vollständigkeit, sollten Sie den Rückgabewert werden überprüft:

fn ime_get(addr: u8) -> Option<i32> { 
    let mut v = 0; 
    let success = unsafe { imeGet(addr, &mut v) }; 

    if success { 
     Some(v) 
    } else { 
     None 
    } 
} 

die Unterschiede zwischen Rust und C in Bezug auf die Weitergabe von Zeigern arbeiten.

Es gibt wirklich keine, auf dieser Ebene.

+0

Ack, weiß nicht, was ich dachte. Vielen Dank! – HotelCalifornia

Verwandte Themen