From 913ca8b7311a7402ec1a1e367b3013924b8557b6 Mon Sep 17 00:00:00 2001 From: Selfhosting Dev Date: Wed, 17 Sep 2025 20:42:01 +0900 Subject: [PATCH] runtime(plugin): unify to Nyash ABI v2 dispatch via shim; loader drops legacy nyash_plugin_invoke and records TypeBox invoke_id; all PluginBoxV2 invoke paths use v2 shim --- .../plugin_loader_v2/enabled/host_bridge.rs | 26 +++++- .../plugin_loader_v2/enabled/loader.rs | 81 ++++++++++--------- src/runtime/plugin_loader_v2/enabled/mod.rs | 26 ++++++ src/runtime/plugin_loader_v2/enabled/types.rs | 1 - 4 files changed, 93 insertions(+), 41 deletions(-) diff --git a/src/runtime/plugin_loader_v2/enabled/host_bridge.rs b/src/runtime/plugin_loader_v2/enabled/host_bridge.rs index 033c87bd..c177b1e5 100644 --- a/src/runtime/plugin_loader_v2/enabled/host_bridge.rs +++ b/src/runtime/plugin_loader_v2/enabled/host_bridge.rs @@ -1,9 +1,27 @@ -// Host bridge helpers for TypeBox invoke (minimal, v2) +// Host bridge helpers for TypeBox invoke (v2) -pub type InvokeFn = - unsafe extern "C" fn(u32, u32, u32, *const u8, usize, *mut u8, *mut usize) -> i32; +// Library-level shim signature used across the runtime (compat convenience) +pub type InvokeFn = unsafe extern "C" fn( + u32, /* type_id (for dispatch) */ + u32, /* method_id */ + u32, /* instance_id */ + *const u8, + usize, + *mut u8, + *mut usize, +) -> i32; -// Call invoke_id with a temporary output buffer; returns (code, bytes_written, buffer) +// Native v2 per-Box signature +pub type BoxInvokeFn = extern "C" fn( + u32, /* instance_id */ + u32, /* method_id */ + *const u8, + usize, + *mut u8, + *mut usize, +) -> i32; + +// Call library-level shim with a temporary output buffer pub fn invoke_alloc( invoke: InvokeFn, type_id: u32, diff --git a/src/runtime/plugin_loader_v2/enabled/loader.rs b/src/runtime/plugin_loader_v2/enabled/loader.rs index d59a5217..c16167c7 100644 --- a/src/runtime/plugin_loader_v2/enabled/loader.rs +++ b/src/runtime/plugin_loader_v2/enabled/loader.rs @@ -1,3 +1,4 @@ +use super::host_bridge::BoxInvokeFn; use super::types::{LoadedPluginV2, NyashTypeBoxFfi, PluginBoxMetadata, PluginBoxV2, PluginHandleInner}; use crate::bid::{BidError, BidResult}; use crate::box_trait::NyashBox; @@ -12,7 +13,7 @@ fn dbg_on() -> bool { std::env::var("NYASH_DEBUG_PLUGIN").unwrap_or_default() == "1" } -type BoxInvokeFn = extern "C" fn(u32, u32, *const u8, usize, *mut u8, *mut usize) -> i32; +// (alias imported from host_bridge) #[derive(Debug, Clone, Default)] struct LoadedBoxSpec { @@ -128,33 +129,24 @@ impl PluginLoaderV2 { let lib = unsafe { Library::new(&lib_path) }.map_err(|_| BidError::PluginError)?; let lib_arc = Arc::new(lib); - // Resolve required invoke symbol (legacy library-level): nyash_plugin_invoke + // Optional init (best-effort) unsafe { - let invoke_sym: Symbol< - unsafe extern "C" fn(u32, u32, u32, *const u8, usize, *mut u8, *mut usize) -> i32, - > = lib_arc - .get(b"nyash_plugin_invoke\0") - .map_err(|_| BidError::PluginError)?; - - // Optional init (best-effort) if let Ok(init_sym) = lib_arc.get:: i32>>(b"nyash_plugin_init\0") { let _ = init_sym(); } - - let loaded = LoadedPluginV2 { - _lib: lib_arc.clone(), - box_types: lib_def.boxes.clone(), - typeboxes: HashMap::new(), - init_fn: None, - invoke_fn: *invoke_sym, - }; - self.plugins - .write() - .map_err(|_| BidError::PluginError)? - .insert(lib_name.to_string(), Arc::new(loaded)); } + let loaded = LoadedPluginV2 { + _lib: lib_arc.clone(), + box_types: lib_def.boxes.clone(), + typeboxes: HashMap::new(), + init_fn: None, + }; + self.plugins + .write() + .map_err(|_| BidError::PluginError)? + .insert(lib_name.to_string(), Arc::new(loaded)); // Try to resolve Nyash ABI v2 per-box TypeBox symbols and record invoke_id // Symbol pattern: nyash_typebox_ @@ -227,13 +219,26 @@ impl PluginLoaderV2 { None } + /// Lookup per-Box invoke function pointer for given type_id via loaded TypeBox specs + pub fn box_invoke_fn_for_type_id(&self, type_id: u32) -> Option { + let config = self.config.as_ref()?; + let cfg_path = self.config_path.as_ref()?; + let toml_str = std::fs::read_to_string(cfg_path).ok()?; + let toml_value: toml::Value = toml::from_str(&toml_str).ok()?; + let (lib_name, box_type) = self.find_box_by_type_id(config, &toml_value, type_id)?; + let key = (lib_name.to_string(), box_type.to_string()); + let map = self.box_specs.read().ok()?; + let spec = map.get(&key)?; + spec.invoke_id + } + pub fn metadata_for_type_id(&self, type_id: u32) -> Option { let config = self.config.as_ref()?; let cfg_path = self.config_path.as_ref()?; let toml_str = std::fs::read_to_string(cfg_path).ok()?; let toml_value: toml::Value = toml::from_str(&toml_str).ok()?; let (lib_name, box_type) = self.find_box_by_type_id(config, &toml_value, type_id)?; - let plugin = { + let _plugin = { let plugins = self.plugins.read().ok()?; plugins.get(lib_name)?.clone() }; @@ -262,7 +267,7 @@ impl PluginLoaderV2 { lib_name: lib_name.to_string(), box_type: box_type.to_string(), type_id: resolved_type, - invoke_fn: plugin.invoke_fn, + invoke_fn: super::super::nyash_plugin_invoke_v2_shim, fini_method_id: fini_method, }) } @@ -278,7 +283,7 @@ impl PluginLoaderV2 { let toml_value: toml::Value = toml::from_str(&toml_str).ok()?; let (lib_name, box_type) = self.find_box_by_type_id(config, &toml_value, type_id)?; let plugins = self.plugins.read().ok()?; - let plugin = plugins.get(lib_name)?.clone(); + let _plugin = plugins.get(lib_name)?.clone(); let fini_method_id = if let Some(spec) = self .box_specs .read() @@ -293,7 +298,7 @@ impl PluginLoaderV2 { let bx = super::types::construct_plugin_box( box_type.to_string(), type_id, - plugin.invoke_fn, + super::super::nyash_plugin_invoke_v2_shim, instance_id, fini_method_id, ); @@ -329,7 +334,7 @@ impl PluginLoaderV2 { .map_err(|_| BidError::PluginError)?; let config = self.config.as_ref().ok_or(BidError::PluginError)?; let plugins = self.plugins.read().unwrap(); - let plugin = plugins.get(lib_name).ok_or(BidError::PluginError)?; + let _plugin = plugins.get(lib_name).ok_or(BidError::PluginError)?; let type_id = if let Some(spec) = self .box_specs .read() @@ -348,7 +353,7 @@ impl PluginLoaderV2 { let out_len = out.len(); let tlv_args = crate::runtime::plugin_ffi_common::encode_empty_args(); let (birth_result, _len, out_vec) = - super::host_bridge::invoke_alloc(plugin.invoke_fn, type_id, 0, 0, &tlv_args); + super::host_bridge::invoke_alloc(super::super::nyash_plugin_invoke_v2_shim, type_id, 0, 0, &tlv_args); let out = out_vec; if birth_result != 0 || out_len < 4 { return Err(BidError::PluginError); @@ -369,7 +374,7 @@ impl PluginLoaderV2 { }; let handle = Arc::new(PluginHandleInner { type_id, - invoke_fn: plugin.invoke_fn, + invoke_fn: super::super::nyash_plugin_invoke_v2_shim, instance_id, fini_method_id: fini_id, finalized: std::sync::atomic::AtomicBool::new(false), @@ -583,11 +588,11 @@ impl PluginLoaderV2 { .ok_or(BidError::InvalidMethod)?; // Get plugin handle let plugins = self.plugins.read().map_err(|_| BidError::PluginError)?; - let plugin = plugins.get(lib_name).ok_or(BidError::PluginError)?; + let _plugin = plugins.get(lib_name).ok_or(BidError::PluginError)?; // Encode TLV args via shared helper (numeric→string→toString) let tlv = crate::runtime::plugin_ffi_common::encode_args(args); let (_code, out_len, out) = super::host_bridge::invoke_alloc( - plugin.invoke_fn, + super::super::nyash_plugin_invoke_v2_shim, type_id, method.method_id, instance_id, @@ -629,7 +634,7 @@ impl PluginLoaderV2 { { let handle = Arc::new(super::types::PluginHandleInner { type_id: ret_type, - invoke_fn: plugin.invoke_fn, + invoke_fn: super::super::nyash_plugin_invoke_v2_shim, instance_id: inst, fini_method_id: None, finalized: std::sync::atomic::AtomicBool::new(false), @@ -686,8 +691,7 @@ impl PluginLoaderV2 { let fini_id = box_conf.methods.get("fini").map(|m| m.method_id); // Get loaded plugin invoke - let plugins = self.plugins.read().map_err(|_| BidError::PluginError)?; - let plugin = plugins.get(lib_name).ok_or(BidError::PluginError)?; + let _plugins = self.plugins.read().map_err(|_| BidError::PluginError)?; // Call birth (no args TLV) and read returned instance id (little-endian u32 in bytes 0..4) if dbg_on() { @@ -697,8 +701,13 @@ impl PluginLoaderV2 { ); } let tlv = crate::runtime::plugin_ffi_common::encode_empty_args(); - let (code, out_len, out_buf) = - super::host_bridge::invoke_alloc(plugin.invoke_fn, type_id, birth_id, 0, &tlv); + let (code, out_len, out_buf) = super::host_bridge::invoke_alloc( + super::super::nyash_plugin_invoke_v2_shim, + type_id, + birth_id, + 0, + &tlv, + ); if dbg_on() { eprintln!("[PluginLoaderV2] create_box: box_type={} type_id={} birth_id={} code={} out_len={}", box_type, type_id, birth_id, code, out_len); if out_len > 0 { @@ -717,7 +726,7 @@ impl PluginLoaderV2 { box_type: box_type.to_string(), inner: Arc::new(PluginHandleInner { type_id, - invoke_fn: plugin.invoke_fn, + invoke_fn: super::super::nyash_plugin_invoke_v2_shim, instance_id, fini_method_id: fini_id, finalized: std::sync::atomic::AtomicBool::new(false), diff --git a/src/runtime/plugin_loader_v2/enabled/mod.rs b/src/runtime/plugin_loader_v2/enabled/mod.rs index 08b90d99..83a4225b 100644 --- a/src/runtime/plugin_loader_v2/enabled/mod.rs +++ b/src/runtime/plugin_loader_v2/enabled/mod.rs @@ -17,6 +17,32 @@ pub fn metadata_for_type_id(type_id: u32) -> Option { guard.metadata_for_type_id(type_id) } +/// Resolve per-Box invoke function for a type_id (v2 only) +pub fn box_invoke_for_type_id(type_id: u32) -> Option { + let loader = get_global_loader_v2(); + let guard = loader.read().ok()?; + guard.box_invoke_fn_for_type_id(type_id) +} + +/// Library-level shim to dispatch a v2 per-Box invoke function using type_id +#[no_mangle] +pub extern "C" fn nyash_plugin_invoke_v2_shim( + type_id: u32, + method_id: u32, + instance_id: u32, + args: *const u8, + args_len: usize, + result: *mut u8, + result_len: *mut usize, +) -> i32 { + if let Some(f) = box_invoke_for_type_id(type_id) { + // Safety: Plugin-provided function pointer; adhere to C ABI + return unsafe { f(instance_id, method_id, args, args_len, result, result_len) }; + } + // E_PLUGIN (-5) when not found + -5 +} + pub fn backend_kind() -> &'static str { "enabled" } diff --git a/src/runtime/plugin_loader_v2/enabled/types.rs b/src/runtime/plugin_loader_v2/enabled/types.rs index 1a0d58d2..757a1a4e 100644 --- a/src/runtime/plugin_loader_v2/enabled/types.rs +++ b/src/runtime/plugin_loader_v2/enabled/types.rs @@ -13,7 +13,6 @@ pub struct LoadedPluginV2 { pub(super) box_types: Vec, pub(super) typeboxes: std::collections::HashMap, pub(super) init_fn: Option i32>, - pub(super) invoke_fn: InvokeFn, } #[derive(Clone)]