fix: align runtime ABI — shrink Lua RuntimeInfo, pass owlry_version to init

- Shrink Lua RuntimeInfo from 5 fields to 2 (name, version), matching
  core and Rune. The mismatch caused SIGSEGV across the ABI boundary.
- Add owlry_version parameter to vtable init in all three crates
  (core, Lua, Rune) so runtimes receive the version at init time
  instead of hardcoding it.
- Remove unused Lua constants (RUNTIME_ID, RUNTIME_NAME, etc.) and
  LUA_RUNTIME_API_VERSION.
- Update plugin_commands.rs call sites to pass CARGO_PKG_VERSION.
This commit is contained in:
2026-03-26 17:31:23 +01:00
parent 8073d27df2
commit a2eb7d1b0d
4 changed files with 25 additions and 36 deletions

View File

@@ -56,7 +56,7 @@ pub struct RuntimeHandle(pub *mut ());
#[repr(C)]
pub struct ScriptRuntimeVTable {
pub info: extern "C" fn() -> RuntimeInfo,
pub init: extern "C" fn(plugins_dir: RStr<'_>) -> RuntimeHandle,
pub init: extern "C" fn(plugins_dir: RStr<'_>, owlry_version: RStr<'_>) -> RuntimeHandle,
pub providers: extern "C" fn(handle: RuntimeHandle) -> RVec<ScriptProviderInfo>,
pub refresh: extern "C" fn(handle: RuntimeHandle, provider_id: RStr<'_>) -> RVec<PluginItem>,
pub query: extern "C" fn(
@@ -83,12 +83,13 @@ pub struct LoadedRuntime {
impl LoadedRuntime {
/// Load the Lua runtime from the system directory
pub fn load_lua(plugins_dir: &Path) -> PluginResult<Self> {
pub fn load_lua(plugins_dir: &Path, owlry_version: &str) -> PluginResult<Self> {
Self::load_from_path(
"Lua",
&PathBuf::from(SYSTEM_RUNTIMES_DIR).join("liblua.so"),
b"owlry_lua_runtime_vtable",
plugins_dir,
owlry_version,
)
}
@@ -98,6 +99,7 @@ impl LoadedRuntime {
library_path: &Path,
vtable_symbol: &[u8],
plugins_dir: &Path,
owlry_version: &str,
) -> PluginResult<Self> {
if !library_path.exists() {
return Err(PluginError::NotFound(library_path.display().to_string()));
@@ -124,7 +126,7 @@ impl LoadedRuntime {
// Initialize the runtime
let plugins_dir_str = plugins_dir.to_string_lossy();
let handle = (vtable.init)(RStr::from_str(&plugins_dir_str));
let handle = (vtable.init)(RStr::from_str(&plugins_dir_str), RStr::from_str(owlry_version));
// Get provider information
let providers_rvec = (vtable.providers)(handle);
@@ -266,12 +268,13 @@ pub fn rune_runtime_available() -> bool {
impl LoadedRuntime {
/// Load the Rune runtime from the system directory
pub fn load_rune(plugins_dir: &Path) -> PluginResult<Self> {
pub fn load_rune(plugins_dir: &Path, owlry_version: &str) -> PluginResult<Self> {
Self::load_from_path(
"Rune",
&PathBuf::from(SYSTEM_RUNTIMES_DIR).join("librune.so"),
b"owlry_rune_runtime_vtable",
plugins_dir,
owlry_version,
)
}
}

View File

@@ -33,22 +33,13 @@ use std::path::PathBuf;
use loader::LoadedPlugin;
// Runtime metadata
const RUNTIME_ID: &str = "lua";
const RUNTIME_NAME: &str = "Lua Runtime";
const RUNTIME_VERSION: &str = env!("CARGO_PKG_VERSION");
const RUNTIME_DESCRIPTION: &str = "Lua 5.4 runtime for user plugins";
/// API version for compatibility checking
pub const LUA_RUNTIME_API_VERSION: u32 = 1;
/// Runtime vtable - exported interface for the core to use
#[repr(C)]
pub struct LuaRuntimeVTable {
/// Get runtime info
pub info: extern "C" fn() -> RuntimeInfo,
/// Initialize the runtime with plugins directory
pub init: extern "C" fn(plugins_dir: RStr<'_>) -> RuntimeHandle,
pub init: extern "C" fn(plugins_dir: RStr<'_>, owlry_version: RStr<'_>) -> RuntimeHandle,
/// Get provider infos from all loaded plugins
pub providers: extern "C" fn(handle: RuntimeHandle) -> RVec<LuaProviderInfo>,
/// Refresh a provider's items
@@ -66,11 +57,8 @@ pub struct LuaRuntimeVTable {
/// Runtime info returned by the runtime
#[repr(C)]
pub struct RuntimeInfo {
pub id: RString,
pub name: RString,
pub version: RString,
pub description: RString,
pub api_version: u32,
}
/// Opaque handle to the runtime state
@@ -259,22 +247,15 @@ impl LuaRuntimeState {
extern "C" fn runtime_info() -> RuntimeInfo {
RuntimeInfo {
id: RString::from(RUNTIME_ID),
name: RString::from(RUNTIME_NAME),
version: RString::from(RUNTIME_VERSION),
description: RString::from(RUNTIME_DESCRIPTION),
api_version: LUA_RUNTIME_API_VERSION,
name: RString::from("Lua"),
version: RString::from(env!("CARGO_PKG_VERSION")),
}
}
extern "C" fn runtime_init(plugins_dir: RStr<'_>) -> RuntimeHandle {
extern "C" fn runtime_init(plugins_dir: RStr<'_>, owlry_version: RStr<'_>) -> RuntimeHandle {
let plugins_dir = PathBuf::from(plugins_dir.as_str());
let mut state = Box::new(LuaRuntimeState::new(plugins_dir));
// TODO: Get owlry version from core somehow
// For now, use a reasonable default
state.discover_and_load("0.3.0");
state.discover_and_load(owlry_version.as_str());
RuntimeHandle::from_box(state)
}
@@ -346,8 +327,8 @@ mod tests {
#[test]
fn test_runtime_info() {
let info = runtime_info();
assert_eq!(info.id.as_str(), "lua");
assert_eq!(info.api_version, LUA_RUNTIME_API_VERSION);
assert_eq!(info.name.as_str(), "Lua");
assert!(!info.version.as_str().is_empty());
}
#[test]

View File

@@ -72,7 +72,7 @@ struct RuntimeState {
#[repr(C)]
pub struct RuneRuntimeVTable {
pub info: extern "C" fn() -> RuntimeInfo,
pub init: extern "C" fn(plugins_dir: RStr<'_>) -> RuntimeHandle,
pub init: extern "C" fn(plugins_dir: RStr<'_>, owlry_version: RStr<'_>) -> RuntimeHandle,
pub providers: extern "C" fn(handle: RuntimeHandle) -> RVec<RuneProviderInfo>,
pub refresh: extern "C" fn(handle: RuntimeHandle, provider_id: RStr<'_>) -> RVec<PluginItem>,
pub query: extern "C" fn(
@@ -94,8 +94,9 @@ extern "C" fn runtime_info() -> RuntimeInfo {
}
}
extern "C" fn runtime_init(plugins_dir: RStr<'_>) -> RuntimeHandle {
extern "C" fn runtime_init(plugins_dir: RStr<'_>, owlry_version: RStr<'_>) -> RuntimeHandle {
let _ = env_logger::try_init();
let _version = owlry_version.as_str();
let plugins_dir = PathBuf::from(plugins_dir.as_str());
log::info!(
@@ -250,7 +251,7 @@ mod tests {
let plugins_dir = temp.path().to_string_lossy();
// Initialize runtime
let handle = runtime_init(RStr::from_str(&plugins_dir));
let handle = runtime_init(RStr::from_str(&plugins_dir), RStr::from_str("1.0.0"));
assert!(!handle.0.is_null());
// Get providers (should be empty with no plugins)

View File

@@ -1114,10 +1114,14 @@ fn execute_plugin_command(
// Load the appropriate runtime
let loaded_runtime = match runtime {
PluginRuntime::Lua => LoadedRuntime::load_lua(plugin_path.parent().unwrap_or(plugin_path))
.map_err(|e| format!("Failed to load Lua runtime: {}", e))?,
PluginRuntime::Lua => {
let owlry_version = env!("CARGO_PKG_VERSION");
LoadedRuntime::load_lua(plugin_path.parent().unwrap_or(plugin_path), owlry_version)
.map_err(|e| format!("Failed to load Lua runtime: {}", e))?
}
PluginRuntime::Rune => {
LoadedRuntime::load_rune(plugin_path.parent().unwrap_or(plugin_path))
let owlry_version = env!("CARGO_PKG_VERSION");
LoadedRuntime::load_rune(plugin_path.parent().unwrap_or(plugin_path), owlry_version)
.map_err(|e| format!("Failed to load Rune runtime: {}", e))?
}
};