DEV Community

Vee Satayamas
Vee Satayamas

Posted on

7 1

Calling Rust from Common Lisp

I didn't do anything fancy. I create C compatible wrapper in Rust, and call the wrapper from Common Lisp using CFFI.

My C compatible wrapper functions

#[no_mangle]
pub extern "C" fn zstd_line_read_new<'a>(zstd_file_path: *const c_char) -> *mut c_void {
    let r_zstd_file_path = unsafe { CStr::from_ptr(zstd_file_path) };
    let file = File::open(r_zstd_file_path.to_str().unwrap());
    if file.is_err() {
        eprintln!("Cannot open file {}", r_zstd_file_path.to_str().unwrap());
        return ptr::null::<c_void>() as *mut c_void;
    }
    let file = file.unwrap();
    let wrapper = DecoderWrapper::new(file);
    Box::into_raw(Box::new(wrapper)) as *mut c_void
}

#[no_mangle]
pub extern "C" fn zstd_line_read<'a>(reader: *mut c_void) -> *const c_char {
    let wrapper: *mut DecoderWrapper<'a> = reader as *mut DecoderWrapper<'a>;
    let mut line = Vec::with_capacity(BUF_SIZE);
    unsafe {
        match (*wrapper).read_line(&mut line) {
            Ok(len) => {
                if len == 0 {
                    return ptr::null();
                } else {
                    return CString::from_vec_unchecked(line).into_raw();
                }
            }
            Err(e) => {
                panic!(e)
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

I added this to Carto.toml

[lib]
crate-type = ["cdylib"]
Enter fullscreen mode Exit fullscreen mode

It makes Cargo create DLL on Windows or .so on Linux instead of Rust specific library format.

In my Common Lisp code:

(ql:quickload :cffi)
(defpackage :t1
  (:use :cl :cffi))
(in-package :t1)

(define-foreign-library zstd_read_line
  (:win32 (:default "./target/release/zstd_read_line"))
  (t (:default "./target/release/libzstd_read_line")))

(use-foreign-library zstd_read_line)

(defcfun ("zstd_line_read_new" create-zstd-reader) :pointer (zstd_archive_path :string))
(defcfun ("zstd_line_read" zstd-read-line) :string (reader :pointer))

(let ((reader (create-zstd-reader "test1.txt.zst")))
  (loop for line = (zstd-read-line reader)
    while line
    do (print line)))
Enter fullscreen mode Exit fullscreen mode

It required Quicklisp for install CFFI. This process doesn't require cbindgen because I define C interface in Common Lisp manually, as you may see at defcfun.

And then it works even on Windows 10.

Alt Text

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

Top comments (0)

AWS Security LIVE!

Join us for AWS Security LIVE!

Discover the future of cloud security. Tune in live for trends, tips, and solutions from AWS and AWS Partners.

Learn More

Instrument, monitor, fix: a hands-on debugging session

Join Lazar for a hands-on session where you’ll build it, break it, debug it, and fix it. You’ll set up Sentry, track errors, use Session Replay and Tracing, and leverage some good ol’ AI to find and fix issues fast.

Tune in to the full event

DEV is partnering to bring live events to the community. Join us or dismiss this billboard if you're not interested. ❤️