summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorQrius <[email protected]>2024-12-06 14:23:32 +0100
committerQrius <[email protected]>2024-12-06 14:23:41 +0100
commit1b59010b7da3b86aea6eb929d7efe37bdf735cd6 (patch)
tree568406b02dd280c005a54622b22a025776dcca9a
parent42ec0c6469238b60bfd5f5c0baa085ec0c6ec148 (diff)
downloadskaldpress-1b59010b7da3b86aea6eb929d7efe37bdf735cd6.tar.gz
skaldpress-1b59010b7da3b86aea6eb929d7efe37bdf735cd6.zip
Add some basic bindings for Guile-3.0
-rw-r--r--Cargo.lock4
-rw-r--r--Cargo.toml8
-rw-r--r--build.rs39
-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
-rw-r--r--src/lib.rs2
8 files changed, 145 insertions, 3 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 3e6e350..8244f98 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -109,9 +109,9 @@ dependencies = [
[[package]]
name = "libc"
-version = "0.2.158"
+version = "0.2.167"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439"
+checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc"
[[package]]
name = "log"
diff --git a/Cargo.toml b/Cargo.toml
index 08464fa..3665cb6 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -5,16 +5,18 @@ edition = "2021"
default-run = "skaldpress"
[features]
-default = ["time", "markdown", "deadlinks"]
+default = ["time", "markdown", "deadlinks", "guile"]
time = ["dep:chrono"]
markdown = ["dep:markdown"]
deadlinks = ["dep:minreq"]
webring = []
+guile = []
[dependencies]
markdown = { version = "1.0.0-alpha.20", optional = true }
chrono = { version = "0.4.38", optional = true }
minreq = { version = "2.12.0", optional = true, features = ["https", "punycode"] }
+#libc = { version = "0.2.167", optional = true }
[[bin]]
name = "skaldpress"
@@ -25,3 +27,7 @@ path = "src/skaldpress/main.rs"
[[bin]]
name = "smp"
path = "src/macro_processor/main.rs"
+
+[[bin]]
+name = "guiletest"
+path = "src/guile/main.rs"
diff --git a/build.rs b/build.rs
new file mode 100644
index 0000000..83fcc3c
--- /dev/null
+++ b/build.rs
@@ -0,0 +1,39 @@
+#[cfg(feature = "guile")]
+use std::env;
+#[cfg(feature = "guile")]
+use std::process::Command;
+
+// cargo build has to be run twice for some reason.
+fn build_guile() {
+ const LIBGUILE_INCLUDE_PATH: &str = "/usr/include/guile/3.0/";
+ const GUILEDEFS_SRC: &str = "src/guile/guiledefs.c";
+ const GUILEDEFS_TARGET_OBJ: &str = "guiledefs.o";
+ const GUILEDEFS_TARGET_ARCHIVE: &str = "libguiledefs.a";
+
+ let out_dir = env::var("OUT_DIR").unwrap();
+
+ Command::new("gcc")
+ .arg("-c")
+ .arg("-I")
+ .arg(LIBGUILE_INCLUDE_PATH)
+ .arg("-lguile-3.0")
+ .arg(GUILEDEFS_SRC)
+ .arg("-o")
+ .arg(format!("{}/{}", out_dir, GUILEDEFS_TARGET_OBJ))
+ .spawn()
+ .expect("Error compiling guiledefs.c");
+
+ Command::new("ar")
+ .arg("r")
+ .arg(format!("{}/{}", out_dir, GUILEDEFS_TARGET_ARCHIVE))
+ .arg(format!("{}/{}", out_dir, GUILEDEFS_TARGET_OBJ))
+ .spawn()
+ .expect("Error creating libguiledefs.a");
+
+ println!("cargo:rustc-link-search=native={}", out_dir);
+}
+
+fn main() {
+ #[cfg(feature = "guile")]
+ build_guile();
+}
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;
diff --git a/src/lib.rs b/src/lib.rs
index 7898aa2..6e23d81 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,2 +1,4 @@
+#[cfg(feature = "guile")]
+pub mod guile;
pub mod macro_processor;
pub mod skaldpress;