use eclisp::{Lisp, LispContext, LispError, sys};
struct Transform {
x: f32,
}
unsafe extern "C" fn transform_x(ptr: sys::cl_object) -> sys::cl_object {
let transform = unsafe { &*sys::ecl_foreign_data_pointer_safe(ptr).cast::<Transform>() };
unsafe { sys::ecl_make_single_float(transform.x) }
}
unsafe extern "C" fn transform_sum(left: sys::cl_object, right: sys::cl_object) -> sys::cl_object {
let left = unsafe { &*sys::ecl_foreign_data_pointer_safe(left).cast::<Transform>() };
let right = unsafe { &*sys::ecl_foreign_data_pointer_safe(right).cast::<Transform>() };
unsafe { sys::ecl_make_single_float(left.x + right.x) }
}
fn native_getter(ctx: &LispContext<'_>) -> Result<(), LispError> {
let mut transform = Transform { x: 42.0 };
eclisp::defun_native!(ctx, "%transform-x", transform_x; (_))?;
let foreign = unsafe { ctx.foreign_data(std::ptr::addr_of!(transform))? };
let result = ctx.call("%transform-x", &[&foreign])?;
assert_eq!(result.try_as_f64()?, 42.0);
transform.x = 84.0;
assert_eq!(transform.x, 84.0);
let result = ctx.call("%transform-x", &[&foreign])?;
assert_eq!(result.try_as_f64()?, 84.0);
Ok(())
}
fn native_multiple_objects(ctx: &LispContext<'_>) -> Result<(), LispError> {
let left = Transform { x: 20.0 };
let right = Transform { x: 22.0 };
eclisp::defun_native!(ctx, "%transform-sum", transform_sum; (_, _))?;
let left = unsafe { ctx.foreign_data(std::ptr::addr_of!(left))? };
let right = unsafe { ctx.foreign_data(std::ptr::addr_of!(right))? };
let result = ctx.call("%transform-sum", &[&left, &right])?;
assert_eq!(result.try_as_f64()?, 42.0);
Ok(())
}
fn run(name: &str, lisp: &LispContext<'_>, test: fn(&LispContext<'_>) -> Result<(), LispError>) {
print!("test {name} ... ");
match test(lisp) {
Ok(()) => println!("ok"),
Err(error) => panic!("{name} failed: {error}"),
}
}
fn main() -> Result<(), LispError> {
let lisp = Lisp::new()?;
lisp.enter(|ctx| {
run("native_getter", &ctx, native_getter);
run("native_multiple_objects", &ctx, native_multiple_objects);
});
Ok(())
}