2026-02-19 13:46:54 +00:00
|
|
|
#![allow(dead_code)]
|
|
|
|
|
|
2026-02-19 11:08:20 +00:00
|
|
|
use std::ffi::{CStr, c_char};
|
Call Rust from Haskell with `cargo-cabal` and `hs-bindgen`
See https://sraka.xyz/posts/hs-bindgen-introduction.html.
For now, this is a shell-based workflow, rather than using Nix to build everything, i.e. `nix develop` works but `nix build` doesn't. And `cargo build` has to be called manually to create the C library, rather than `cabal` being clever enough to invoke it itself.
We ran `cargo cabal init` from the `rust` directory (`nix shell github:yvan-sraka/cargo-cabal`), which generated `hsbindgen.toml` (which we use), and `Setup.lhs` (which just added `extra-lib-dirs`, and with the wrong paths, so we dspecify those statically instead in `garnet.cabal`). We also follow its advice to use `staticlib`.
Also, after we ran the first `cargo build` (requiring a `mkdir rust/src` before it would run), we took the generated the Haskell file, and moved the main contents in to `Main.hs` manually.
2026-02-18 15:49:08 +00:00
|
|
|
|
2026-02-19 11:08:20 +00:00
|
|
|
fn say_hello(name: &str) {
|
Call Rust from Haskell with `cargo-cabal` and `hs-bindgen`
See https://sraka.xyz/posts/hs-bindgen-introduction.html.
For now, this is a shell-based workflow, rather than using Nix to build everything, i.e. `nix develop` works but `nix build` doesn't. And `cargo build` has to be called manually to create the C library, rather than `cabal` being clever enough to invoke it itself.
We ran `cargo cabal init` from the `rust` directory (`nix shell github:yvan-sraka/cargo-cabal`), which generated `hsbindgen.toml` (which we use), and `Setup.lhs` (which just added `extra-lib-dirs`, and with the wrong paths, so we dspecify those statically instead in `garnet.cabal`). We also follow its advice to use `staticlib`.
Also, after we ran the first `cargo build` (requiring a `mkdir rust/src` before it would run), we took the generated the Haskell file, and moved the main contents in to `Main.hs` manually.
2026-02-18 15:49:08 +00:00
|
|
|
println!("Hello from Rust, {name}!");
|
|
|
|
|
}
|
2026-02-19 11:08:20 +00:00
|
|
|
|
|
|
|
|
#[unsafe(no_mangle)]
|
|
|
|
|
extern "C" fn hello(c: *const c_char) -> () {
|
|
|
|
|
say_hello(unsafe { CStr::from_ptr(c) }.to_str().unwrap())
|
|
|
|
|
}
|
2026-02-19 11:11:23 +00:00
|
|
|
|
|
|
|
|
#[repr(C)]
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
struct T {
|
|
|
|
|
a: bool,
|
|
|
|
|
b: u8,
|
|
|
|
|
}
|
|
|
|
|
#[unsafe(no_mangle)]
|
2026-02-19 11:15:38 +00:00
|
|
|
extern "C" fn hello_struct(t: T) -> () {
|
2026-02-19 11:11:23 +00:00
|
|
|
say_hello(&format!("{:?}", t))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[repr(C, u8)]
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
enum Shape {
|
|
|
|
|
Circle { radius: f64 },
|
|
|
|
|
Rectangle { width: f64, height: f64 },
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[unsafe(no_mangle)]
|
2026-02-19 11:15:38 +00:00
|
|
|
extern "C" fn hello_shape(s: Shape) -> () {
|
2026-02-19 11:11:23 +00:00
|
|
|
say_hello(&format!("{:?}", s))
|
|
|
|
|
}
|
2026-02-19 15:26:27 +00:00
|
|
|
|
2026-02-19 15:56:55 +00:00
|
|
|
/// cbindgen:prefix=__attribute__((const))
|
2026-02-19 15:26:27 +00:00
|
|
|
#[unsafe(no_mangle)]
|
2026-02-19 15:47:55 +00:00
|
|
|
extern "C" fn add(a: i64, b: i64) -> i64 {
|
2026-02-19 15:26:27 +00:00
|
|
|
a + b
|
|
|
|
|
}
|