summaryrefslogtreecommitdiff
path: root/src/guile
diff options
context:
space:
mode:
Diffstat (limited to 'src/guile')
-rw-r--r--src/guile/guile.rs86
-rw-r--r--src/guile/guiledefs.c3
-rw-r--r--src/guile/main.rs5
-rw-r--r--src/guile/mod.rs1
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;