typst-cffi

Crates.iotypst-cffi
lib.rstypst-cffi
version0.5.0
created_at2025-10-31 14:13:41.146462+00
updated_at2026-01-08 09:02:09.919512+00
descriptionFFI to Typst
homepagehttps://codeberg.org/sbinet/typst-cffi
repositoryhttps://codeberg.org/sbinet/typst-cffi
max_upload_size
id1910107
size9,909,962
Sebastien Binet (sbinet)

documentation

README

typst-cffi

Release License

typst-cffi is a simple-minded C-FFI Rust library, exposing a subset of the Typst API to C.

Documentation

Documentation is served at docs.rs.

Installation

$> cargo add typst-cffi

Examples

use std::ffi::{CStr, CString};
use std::fs::File;
use std::io::Write;

use typst_cffi;

fn main() {
    let src = r#"#set document(
  date: datetime(year:2009,month:11,day:10), // for reproducibility
  author: "typst-cffi",
)

#set page(width: 200pt, height: 300pt)
#set text(font: "New Computer Modern", weight: 450)

#show raw: set text(font: "New Computer Modern Mono", weight: 450)

= H1
== H2
=== H3

Hell·o from `Typ·st` via a _C·FFI_.

$ sum_(k=1)^n k = (n(n+1)) / 2 $

List:
- item `a`
- item `b`

Enumeration:
+ item `a`
+ item `b`

*Bye.*
"#;

    let c_src = match CString::new(src) {
        Ok(c_str) => c_str,
        Err(e) => {
            panic!("Failed to create CString: {}", e);
        }
    };

    let ctx = unsafe { typst_cffi::typst_compile(c_src.as_ptr()) };
    if ctx.is_null() {
        panic!("compilation failed: NULL pointer");
    }

    let err = unsafe { typst_cffi::typst_get_err(ctx) };
    if !err.is_null() {
        let msg = unsafe { CStr::from_ptr(err) };
        unsafe {
            typst_cffi::typst_free(ctx);
        }
        panic!("compilation failed: {:?}", msg);
    }

    unsafe {
        typst_cffi::typst_compile_pdf(ctx);
    }

    let err = unsafe { typst_cffi::typst_get_err(ctx) };
    if !err.is_null() {
        let msg = unsafe { CStr::from_ptr(err) };
        unsafe {
            typst_cffi::typst_free(ctx);
        }
        panic!("compilation failed: {:?}", msg);
    }

    let mut len: usize = 0;
    let buf = unsafe { typst_cffi::typst_get_buf(ctx, &mut len) };
    if buf.is_null() {
        unsafe {
            typst_cffi::typst_free(ctx);
        }
        panic!("compilation failed: NULL pointer to PDF document");
    }

    let pdf = unsafe { std::slice::from_raw_parts(buf, len) };

    let mut f = match File::create("examples/simple.pdf") {
        Ok(f) => f,
        Err(e) => {
            eprintln!("Failed to create output file: {}", e);
            unsafe {
                typst_cffi::typst_free(ctx);
            }
            return;
        }
    };

    if let Err(e) = f.write_all(pdf) {
        eprintln!("could not write PDF data: {e}");
    } else {
        println!("PDF generated successfully: output.pdf ({len} bytes)");
    }

    unsafe {
        typst_cffi::typst_free(ctx);
    }
}

License

typst-cffi is released under the BSD-3 license.

Commit count: 18

cargo fmt