| Crates.io | typst-cffi |
| lib.rs | typst-cffi |
| version | 0.5.0 |
| created_at | 2025-10-31 14:13:41.146462+00 |
| updated_at | 2026-01-08 09:02:09.919512+00 |
| description | FFI to Typst |
| homepage | https://codeberg.org/sbinet/typst-cffi |
| repository | https://codeberg.org/sbinet/typst-cffi |
| max_upload_size | |
| id | 1910107 |
| size | 9,909,962 |
typst-cffi is a simple-minded C-FFI Rust library, exposing a subset of the Typst API to C.
Documentation is served at docs.rs.
$> cargo add typst-cffi
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);
}
}
typst-cffi is released under the BSD-3 license.