Ich schreibe einen Wrapper/FFI für eine C-Bibliothek, die einen globalen Initialisierungsaufruf im Hauptthread sowie einen für die Zerstörung erfordert.Empfohlene Methode zum Umschließen von C lib-Initialisierungs-/Zerstörungsroutine
Hier ist, wie ich bin derzeit Umgang es:
struct App;
impl App {
fn init() -> Self {
unsafe { ffi::InitializeMyCLib(); }
App
}
}
impl Drop for App {
fn drop(&mut self) {
unsafe { ffi::DestroyMyCLib(); }
}
}
, die wie verwendet werden kann:
fn main() {
let _init_ = App::init();
// ...
}
Dies funktioniert gut, aber es fühlt sich an wie ein Hack, um diese Anrufe auf die Lebenszeit binden einer unnötigen Struktur. Die Verwendung des Destruktors in einem finally
(Java) oder at_exit
(Ruby) Block scheint theoretisch geeigneter zu sein.
Gibt es in Rust etwas eleganteres?
EDIT
Wäre es möglich/sicher sein, diese Einrichtung zu verwenden, wie so (mit der lazy_static
Kiste), statt meinem zweiten Block oben:
lazy_static! {
static ref APP: App = App::new();
}
Würde dieses Verweis auf garantiert werden vor jedem anderen Code initialisiert und beim Beenden zerstört werden? Ist es eine schlechte Übung, in einer Bibliothek zu verwenden?
Dies würde es auch erleichtern, den Zugriff auf das FFI durch diese eine Struktur zu erleichtern, da ich nicht die Referenz auf die instantiierte Struktur weitergeben müsste (in meinem ursprünglichen Beispiel _init_
genannt).
Dies würde es auch in gewisser Weise sicherer, da ich die App
struct Standardkonstruktors privat machen könnte.
Side-Note: Abhängig davon, wie sicher Ihr Wrapper sein soll, sollten Sie die 'init'-Funktion unsicher machen (weil niemand sie mehrfach aufrufen darf), und alle Funktionen implementieren, die den clib initialisieren müssen auf dem 'App' Objekt. Auf diese Weise kann niemand die Funktionen aufrufen, ohne sie initialisiert zu haben. Sie können es auch als eine Art Referenzzähler implementieren, um die Initialisierung zu erleichtern. Das ist ein großer Gewinn gegenüber Java und Ruby, weil man dort die Funktionen aufrufen kann, ohne die Lib –
* im Hauptthread zu initialisieren * - bist du sicher, dass es der Hauptthread sein muss? Kann es ein beliebiger Thread sein, solange er vor der Verwendung initialisiert wird? – Shepmaster
@ker, danke für den Kommentar. Ich hatte nicht so darüber nachgedacht (Zugang über die 'App'-Struktur zu haben, aber das macht Sinn. Ich muss darüber nachdenken, ob das für meinen Fall funktionieren würde.) –