diff options
Diffstat (limited to 'src/guile')
| -rw-r--r-- | src/guile/guile.rs | 86 | ||||
| -rw-r--r-- | src/guile/guiledefs.c | 3 | ||||
| -rw-r--r-- | src/guile/main.rs | 5 | ||||
| -rw-r--r-- | src/guile/mod.rs | 1 | 
4 files changed, 95 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)); +    } +} diff --git a/src/guile/guiledefs.c b/src/guile/guiledefs.c new file mode 100644 index 0000000..9f52c43 --- /dev/null +++ b/src/guile/guiledefs.c @@ -0,0 +1,3 @@ +#include <libguile.h> + +struct scm_unused_struct * scm_undefined = SCM_UNDEFINED; diff --git a/src/guile/main.rs b/src/guile/main.rs new file mode 100644 index 0000000..6957c8c --- /dev/null +++ b/src/guile/main.rs @@ -0,0 +1,5 @@ +use skaldpress::guile::guile::testguile; + +fn main() { +    testguile(); +} diff --git a/src/guile/mod.rs b/src/guile/mod.rs new file mode 100644 index 0000000..2368e61 --- /dev/null +++ b/src/guile/mod.rs @@ -0,0 +1 @@ +pub mod guile;  | 
