メインスレッドと破壊用のグローバル初期化コールを必要とするCライブラリ用のラッパー/ FFIを作成しています。ここでCライブラリの初期化/破壊ルーチンをラップするのに推奨される方法
は、私は現在、それを処理しています方法です:
のように使用することができstruct App;
impl App {
fn init() -> Self {
unsafe { ffi::InitializeMyCLib(); }
App
}
}
impl Drop for App {
fn drop(&mut self) {
unsafe { ffi::DestroyMyCLib(); }
}
}
:これは正常に動作しますが、それはハックのように感じ、生涯にこれらの呼び出しを結ぶ
fn main() {
let _init_ = App::init();
// ...
}
不要な構造体のfinally
(Java)またはat_exit
(Ruby)ブロック内にデストラクタを持つことは、理論的にはより適切なようです。
ルストでこれを行うにはもっと優雅な方法がありますか?上記
代わりに私の第二のブロックのEDIT
(lazy_static
クレートを使用して)そのように、この設定を使用しても安全/可能でしょう、:
lazy_static! {
static ref APP: App = App::new();
}
は、この文献は保証されるだろう他のコードの前に初期化され、終了時に破棄されますか?ライブラリにlazy_static
を使用することは悪い習慣ですか?
これは、インスタンス化された構造体(元の例では_init_
と呼ばれます)への参照を回避する必要がないため、この1つの構造体を介してFFIへのアクセスを容易にします。
これは、App
構造体のデフォルトのコンストラクタをprivateにすることができるため、いくつかの点でより安全になります。
サイドノート:あなたのラッパーの安全性に応じて、 'init'関数を安全にしないでください(誰も何度も呼び出さないかもしれないので)。そして、clibをメソッドとして初期化する必要があるすべての関数を実装してください'App'オブジェクトに追加します。このようにして、誰も関数を初期化せずに呼び出すことはできません。初期化するのを安全にするために、何らかのリファレンスカウントシングルトンとして実装することもできます。 JavaとRubyよりも大きな勝利です。なぜなら、メインスレッドでlib –
*を初期化せずに関数を呼び出すことができるからです。*あなたは**本当に**メインスレッドでなければなりませんか?使用前に初期化されている限り、どのスレッドでもかまいませんか? – Shepmaster
@ker、コメントありがとうございます。私はそのようなことは考えていませんでした。( 'App'構造体を通してすべてのアクセスを持っていますが、それは意味があります。)私のケースでこれがうまくいくかどうか考える必要があります。 –