diff options
author | Qrius <[email protected]> | 2024-12-06 14:23:32 +0100 |
---|---|---|
committer | Qrius <[email protected]> | 2024-12-06 14:23:41 +0100 |
commit | 1b59010b7da3b86aea6eb929d7efe37bdf735cd6 (patch) | |
tree | 568406b02dd280c005a54622b22a025776dcca9a /src/guile/guile.rs | |
parent | 42ec0c6469238b60bfd5f5c0baa085ec0c6ec148 (diff) | |
download | skaldpress-1b59010b7da3b86aea6eb929d7efe37bdf735cd6.tar.gz skaldpress-1b59010b7da3b86aea6eb929d7efe37bdf735cd6.zip |
Add some basic bindings for Guile-3.0
Diffstat (limited to 'src/guile/guile.rs')
-rw-r--r-- | src/guile/guile.rs | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/src/guile/guile.rs b/src/guile/guile.rs new file mode 100644 index 0000000..4a0e25b --- /dev/null +++ b/src/guile/guile.rs @@ -0,0 +1,86 @@ +use std::ffi::{CStr, CString}; +use std::os::raw::{c_char, c_int, c_void}; + +#[link(name = "guile-3.0")] +#[allow(dead_code)] +extern "C" { + fn scm_init_guile(); + fn scm_c_define_gsubr( + name: *const c_char, + req: c_int, + opt: c_int, + rst: c_int, + func: extern "C" fn() -> *mut c_void, + ); + fn scm_c_eval_string(expr: *const c_char) -> *mut c_void; + fn scm_to_locale_string(scm_obj: *mut c_void) -> *const c_char; + fn scm_c_write(scm_obj: *mut c_void, port: *mut c_void); + fn scm_open_output_string() -> *mut c_void; + fn scm_get_output_string(port: *mut c_void) -> *mut c_void; + fn scm_is_string(scm_obj: *mut c_void) -> c_int; + fn scm_is_number(scm_obj: *mut c_void) -> c_int; + fn scm_object_to_string(scm_obj: *mut c_void, printer: *mut c_void) -> *mut c_void; +} + +#[link(name = "guiledefs")] +extern "C" { + pub static scm_undefined: *mut c_void; +} + +extern "C" fn my_rust_function() -> *mut c_void { + println!("Hello from Rust!"); + unsafe { scm_undefined } +} + +/// Convert a scm object into a string using Guile-builtins +fn string_from_scm(scm_obj: *mut c_void) -> Result<String, ()> { + unsafe { + if scm_obj.is_null() { + return Err(()); + } + if scm_is_string(scm_obj) != 0 { + let res_str = CStr::from_ptr(scm_to_locale_string(scm_obj)) + .to_string_lossy() + .into_owned(); + return Ok(res_str); + } else { + let port = scm_open_output_string(); + if port.is_null() { + return Err(()); + } + let res = scm_object_to_string(scm_obj, scm_undefined); + if res.is_null() { + return Err(()); + } + let res_str = CStr::from_ptr(scm_to_locale_string(res)) + .to_string_lossy() + .into_owned(); + return Ok(res_str); + } + } +} + +pub fn smp_guile_init() {} + +pub fn testguile() { + unsafe { + scm_init_guile(); + + let func_name = CString::new("my-rust-function").unwrap(); + scm_c_define_gsubr( + func_name.as_ptr(), + 0, // required arguments + 0, // optional arguments + 0, // rest arguments + my_rust_function, + ); + + let expr = CString::new("(+ 2 3)").unwrap(); + let result = scm_c_eval_string(expr.as_ptr()); + println!("{:?}", string_from_scm(result)); + + let expr = CString::new("(my-rust-function)").unwrap(); + let result = scm_c_eval_string(expr.as_ptr()); + println!("{:?}", string_from_scm(result)); + } +} |