diff --git a/README.md b/README.md
index 44530a6..b41e400 100644
--- a/README.md
+++ b/README.md
@@ -142,6 +142,11 @@ cout << "Alignment score " << aligner.getAlignmentScore() << endl;
**IMPORTANT.** Once an alignment object is created, **it is strongly recommended to reuse it to compute multiple alignments**. Creating and destroying the alignment object for every alignment computed can have a significant overhead. Reusing the alignment object allows repurposing internal data structures, minimising the cost of memory allocations, and avoiding multiple alignment setups and precomputations.
+### 2.3 Rust bindings
+
+Rust bindings can be generated automatically using `bindgen`, see [bindings/rust/build.rs](bindings/rust/build.rs).
+An example of how to use them is [here](./bindings/rust/example.rs).
+
## 3. WFA2-LIB FEATURES
* **Exact alignment** method that computes the optimal **alignment score** and/or **alignment CIGAR**.
diff --git a/bindings/rust/build.rs b/bindings/rust/build.rs
new file mode 100644
index 0000000..fcb41a2
--- /dev/null
+++ b/bindings/rust/build.rs
@@ -0,0 +1,65 @@
+//! WFA bindings for rust using Bindgen.
+//!
+//! First, add `bindgen` to your dependencies:
+//! ```toml
+//! [build-dependencies]
+//! bindgen = "0.60.1"
+//! ```
+//!
+//! Then save this file as `build.rs` in the root of your crate.
+//! Update the paths below to match your WFA installation/repository.
+//!
+//! The example has the WFA2-lib repository cloned in `../wfa2`.
+//! Make sure to run `make lib_wfa` in the WFA repository.
+//! The code below will tell cargo to link against `../wfa2/lib/libwfa.a`.
+//!
+//! The bindings will be writted to a special `OUT_DIR` set by cargo. See
+//! `example.rs` for an example of how to include and use the generated
+//! bindings.
+
+extern crate bindgen;
+
+use std::env;
+use std::path::PathBuf;
+
+fn wfa() {
+ // 1. Link instructions for Cargo.
+
+ // The directory of the WFA libraries, added to the search path.
+ println!("cargo:rustc-link-search=../wfa2/lib");
+ // Link the `wfa-lib` library.
+ println!("cargo:rustc-link-lib=wfa");
+ // Also link `omp`.
+ println!("cargo:rustc-link-lib=omp");
+ // Invalidate the built crate whenever the linked library changes.
+ println!("cargo:rerun-if-changed=../wfa2/lib/libwfa.a");
+
+ // 2. Generate bindings.
+
+ let bindings = bindgen::Builder::default()
+ // Generate bindings for this header file.
+ .header("../wfa2/wavefront/wavefront_align.h")
+ // Add this directory to the include path to find included header files.
+ .clang_arg("-I../wfa2")
+ // Generate bindings for all functions starting with `wavefront_`.
+ .allowlist_function("wavefront_.*")
+ // Generate bindings for all variables starting with `wavefront_`.
+ .allowlist_var("wavefront_.*")
+ // Invalidate the built crate whenever any of the included header files
+ // changed.
+ .parse_callbacks(Box::new(bindgen::CargoCallbacks))
+ // Finish the builder and generate the bindings.
+ .generate()
+ // Unwrap the Result and panic on failure.
+ .expect("Unable to generate bindings");
+
+ // Write the bindings to the $OUT_DIR/bindings_wfa.rs file.
+ let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
+ bindings
+ .write_to_file(out_path.join("bindings_wfa.rs"))
+ .expect("Couldn't write bindings!");
+}
+
+fn main() {
+ wfa();
+}
diff --git a/bindings/rust/example.rs b/bindings/rust/example.rs
new file mode 100644
index 0000000..0ac3cc4
--- /dev/null
+++ b/bindings/rust/example.rs
@@ -0,0 +1,46 @@
+/// Include the generated bindings into a separate module.
+#[allow(non_upper_case_globals)]
+#[allow(non_snake_case)]
+#[allow(non_camel_case_types)]
+#[allow(unused)]
+mod wfa {
+ include!(concat!(env!("OUT_DIR"), "/bindings_wfa.rs"));
+}
+
+/// Compute the affine alignment score between `a` and `b` with the given substitution,
+/// gap-open, and gap-extend penalties.
+fn linear_score(a: &[i8], b: &[i8], sub: i32, indel: i32) -> i32 {
+ unsafe {
+ let mut attributes = wfa::wavefront_aligner_attr_default;
+ // Do not use a heuristic (enabled by default).
+ attributes.heuristic.strategy = wfa::wf_heuristic_strategy_wf_heuristic_none;
+ // Only compute the score (not a path).
+ attributes.alignment_scope = wfa::alignment_scope_t_compute_score;
+
+ // Set the cost model and parameters.
+ attributes.distance_metric = wfa::distance_metric_t_gap_affine;
+ attributes.affine_penalties.mismatch = mismatch as i32;
+ attributes.affine_penalties.gap_opening = gap_open as i32;
+ attributes.affine_penalties.gap_extension = gap_extend as i32;
+
+ // Initialize the aligner object.
+ // This should be reused for multiple queries.
+ let wf_aligner = wfa::wavefront_aligner_new(&mut attributes);
+
+ // Do the alignment.
+ let status = wfa::wavefront_align(
+ wf_aligner,
+ a.as_ptr(),
+ a.len() as i32,
+ b.as_ptr(),
+ b.len() as i32,
+ );
+ assert_eq!(status, 0);
+
+ let score = (*wf_aligner).cigar.score;
+
+ // Clean up memory.
+ wfa::wavefront_aligner_delete(wf_aligner);
+ score
+ }
+}