Files
unshell/unshell-modules/src/lib.rs
T

78 lines
2.5 KiB
Rust
Raw Normal View History

2025-11-06 00:01:46 -07:00
#[macro_use]
extern crate log;
mod logger;
2025-11-06 15:49:47 -07:00
mod manager;
2025-11-06 00:01:46 -07:00
mod module;
pub use logger::setup_logger;
2025-11-06 15:49:47 -07:00
pub use manager::Manager;
2025-11-06 00:01:46 -07:00
pub use module::Module;
2025-11-06 15:49:47 -07:00
///Generic error type for module-related operations.
2025-11-06 00:01:46 -07:00
#[derive(Debug)]
pub enum ModuleError {
LibLoadingError(libloading::Error),
2025-11-06 15:49:47 -07:00
LogError(log::SetLoggerError),
2025-11-06 00:01:46 -07:00
LinkError(String),
2025-11-06 15:49:47 -07:00
Error(String),
2025-11-06 00:01:46 -07:00
}
2025-11-06 15:49:47 -07:00
/// Trait for defining modules that have a runtime.
pub trait ModuleRuntime: Send {
/// Returns true if the module is running.
/// After returning false, the module will be dropped.
fn is_running(&self) -> bool;
/// Consumes the module, implementation should kill whatever is running.
fn kill(self: Box<Self>);
}
/// "Module Interface" helper macro that creates a struct with function pointers
/// Useful for defining and requiring modules' functions accross FFI boundry.
2025-11-05 15:17:31 -07:00
#[macro_export]
macro_rules! module_interface {
2025-11-06 15:49:47 -07:00
($(#[$struct_meta:meta])* $interface_name:ident { $($(#[$fn_meta:meta])* fn $fn_name:ident $(<$($gen:ident),+ $(,)?>)?($($arg:ident : $ty:ty),* $(,)?) $(-> $ret:ty)? $(where $($where_clause:tt)*)?);* $(;)? }) => {
2025-11-05 15:17:31 -07:00
#[repr(C)]
#[allow(non_camel_case_types)]
#[derive(Clone, Copy)]
2025-11-06 15:49:47 -07:00
#[allow(improper_ctypes_definitions)]
$(#[$struct_meta])*
2025-11-05 15:17:31 -07:00
pub struct $interface_name {
$(
2025-11-06 15:49:47 -07:00
// This line will FAIL TO COMPILE if you use generics in the macro input.
// You MUST use concrete types like *mut c_void for "generic" data.
2025-11-05 15:17:31 -07:00
$fn_name: extern "C" fn($($ty),*) $(-> $ret)?,
)*
}
impl $interface_name {
2025-11-06 15:49:47 -07:00
$(
#[inline(always)]
$(#[$fn_meta])* // Propagate function attributes
// This is the fix for the `impl` block.
// It adds the captured generics and where-clause to the wrapper function.
pub fn $fn_name $(<$($gen),+>)? (&self, $($arg: $ty),*) $(-> $ret)?
$(where $($where_clause)*)?
{
(self.$fn_name)($($arg),*)
}
)*
2025-11-05 15:17:31 -07:00
/// Create from raw function pointers
///
/// # Safety
///
/// The caller must ensure all function pointers are valid and have
/// the correct signatures
2025-11-05 22:59:01 -07:00
pub fn from_raw(
2025-11-05 15:17:31 -07:00
$($fn_name: extern "C" fn($($ty),*) $(-> $ret)?),*
) -> Self {
Self {
$($fn_name),*
}
}
}
};
}