use crate::{ffi, Error, Fiber, IntoJanet, VM}; #[derive(Debug, Clone, Copy)] pub struct CFunction { name: &'static str, raw: ffi::JanetCFunction, } impl CFunction { pub const fn new(name: &'static str, raw: ffi::JanetCFunction) -> Self { Self { name, raw } } pub const fn name(&self) -> &'static str { self.name } pub const fn raw(&self) -> ffi::JanetCFunction { self.raw } /// Create a new fiber from this C function with the given arguments. /// /// The returned fiber is in the `:new` state. Use [`Fiber::resume`] to start /// it synchronously, or schedule it on the event loop. pub fn create_fiber<'vm, V, Ve>(&self, vm: &'vm VM, args: Ve) -> Result, Error> where Ve: Into>, V: IntoJanet<'vm>, { vm.cfunction_call_fiber(self.raw, args) } } pub trait JanetFnBinding { fn cfunction() -> CFunction; } impl VM { pub fn register_cfunction(&self, cfunction: CFunction) -> Result<(), Error> { unsafe { let c_name = std::ffi::CString::new(cfunction.name()) .map_err(|_| Error::Conversion("invalid C function name".to_string()))?; let wrapped = ffi::janet_wrap_cfunction(cfunction.raw()); ffi::janet_def(self.core_env, c_name.as_ptr(), wrapped, std::ptr::null()); } Ok(()) } pub fn register(&self) -> Result<(), Error> where T: JanetFnBinding, { self.register_cfunction(T::cfunction()) } }