5.1 KiB
5.1 KiB
プラグインBoxのライフサイクル(v2)と nyash.toml 定義
本書は、プラグインBox(PluginBoxV2)の生成(birth)と終了(fini)の流れ、singleton オプション、ならびに nyash.toml v2 における methods 定義の役割をまとめたものです。
1. 用語
- birth: プラグインBoxのインスタンス生成(
method_id=0) - fini: プラグインBoxの終了処理(任意の
method_id。例:4294967295) - invoke_fn: プラグイン側の単一エントリポイント(
nyash_plugin_invoke)
2. 生成(birth)の流れ
unified registryがPluginLoaderV2::create_box(box_type, args)を呼び出す。PluginLoaderV2はnyash.tomlからtype_idとmethodsを読み込む。invoke_fn(type_id, method_id=0 /* birth */, instance_id=0, ...)を呼び、戻り値(出力TLV)の先頭4バイトからinstance_idを取得。PluginBoxV2 { box_type, inner: Arc<PluginHandleInner> }を生成して返す。PluginHandleInnerは{ type_id, instance_id, invoke_fn, fini_method_id, finalized }を保持し、参照カウント(Arc)で共有される。
補足:
fini_method_idはnyash.tomlのmethodsからfiniのmethod_idを取り出して保持します。未定義の場合はNone。
3. 終了(fini)の流れ(現在)
- フィールド差し替え時(代入で旧値を置き換えるとき):
- 旧値が
InstanceBoxの場合: インタプリタがfini()を呼び、finalized としてマーキングします。 - 旧値が
PluginBoxV2の場合:fini_method_idが設定されていればinvoke_fn(type_id, fini_method_id, instance_id, ...)を呼びます。
- 旧値が
- プラグインBox(PluginBoxV2):
- すべての参照(Arc)がDropされ「最後の参照が解放」された時、
Dropで一度だけfiniを呼ぶ(RAII、二重呼び出し防止)。 - 明示finiが必要な場合は
PluginBoxV2::finalize_now()を使える(内部的に一度だけfini実行)。 - 代入/フィールド代入/Map.get/Array.get/slice/退避などは「PluginBoxV2は共有(share)、それ以外は複製(clone)」で統一。
- すべての参照(Arc)がDropされ「最後の参照が解放」された時、
4. nyash.toml v2 の定義例(methods + singleton)
[libraries]
[libraries."libnyash_filebox_plugin.so"]
boxes = ["FileBox"]
path = "./plugins/nyash-filebox-plugin/target/release/libnyash_filebox_plugin.so"
[libraries."libnyash_filebox_plugin.so".FileBox]
type_id = 6
[libraries."libnyash_filebox_plugin.so".FileBox.methods]
birth = { method_id = 0 }
open = { method_id = 1 }
read = { method_id = 2 }
write = { method_id = 3 }
close = { method_id = 4 }
fini = { method_id = 4294967295 } # 任意の終端ID
要点:
methodsにfiniを定義すれば、差し替え時などに fini が呼ばれます。fini未定義の場合、プラグインBoxの終了処理は呼ばれません(フォールバック動作)。
singleton例
[libraries."libnyash_counter_plugin.so".CounterBox]
type_id = 7
singleton = true
[libraries."libnyash_counter_plugin.so".CounterBox.methods]
birth = { method_id = 0 }
inc = { method_id = 1 }
get = { method_id = 2 }
fini = { method_id = 4294967295 }
singleton = trueを設定すると、ローダー初期化時に事前birthし、ローダーが共有ハンドルを保持します。create_box()は保持中の共有ハンドルを返すため、複数回のnewでも同一インスタンスを共有できます。- Nyash終了時(または明示要求時)に
shutdown_plugins_v2()を呼ぶと、ローダーが保持する全シングルトンのfiniを実行し、クリーンに解放されます。
5. WASM(wasm-bindgen)との関係
- WASMターゲットでは
libloadingが使えないため、プラグイン機構は features/cfg でスタブ化しています。 pluginsフィーチャを外す、またはtarget_arch = "wasm32"のときは、プラグイン生成・fini 呼び出しのコードはコンパイル対象外になります(ビルド可能化のため)。
6. 将来拡張の方向
- ローカル変数のスコープ終了時(関数/メソッド呼び出しの戻りなど)に、InstanceBox/PluginBoxV2 の fini を安全に呼び出す仕組み(順序・例外耐性・二重呼び出し防止を含む)。
nyash.tomlにクラス名→プラグインBox型のoverridesを加え、ユーザー定義Boxの外部置換を許可する設計(任意)。
以上。
7. v2.1: BoxRef(Box引数)サポート
目的: プラグインメソッドの引数として、他のBoxインスタンスを不透明参照で受け渡し可能にする。
- 仕様詳細:
docs/reference/plugin-system/nyash-toml-v2_1-spec.md - 設定例(1引数にプラグインBoxを渡す):
[libraries."libnyash_filebox_plugin.so".FileBox.methods]
copyFrom = { method_id = 7, args = [ { kind = "box", category = "plugin" } ] }
注意:
- 当面は
category = "plugin"のみ対応。ユーザー定義Boxや複雑なビルトインBoxは非対応。 - 戻り値の BoxRef は次版(v2.2)で検討。