Rust offers a powerful type system with generics, similar to C++ templates. However, structs and functions with generics cannot be used in C via FFI without monomorphization (i.e. picking a single instance of the generic type or function). This crate defines a macro for the red black tree in sokoban
that facilitates such monomorphization, exposing a simple C-compatible interface for tree initialization, insertion, removal, and retrieval.
This helper macro is defined in sokoban-bindings
, and an example of its use is provided in sokoban-bindings-example
.
The sokoban-bindgen
crate defines the monomorphization helper macro. You must use this macro in your own rust library via
red_black_tree_bindings!(key_type, value_type, capacity);
This will define C-compatible types and functions that use the monomorphized sokoban
types and methods.
You will need
lib-sokoban
- The
cbindgen
crate to generate the C headers, with nightly since the expand feature requres it. (Thesokoban-bindgen
macro must be expanded before cbindgen can parse and generate headers) - The
concat-idents
crate. This is re-exported withinsokoban-bindgen
, so you can get it viause sokoban_bindgen::*
.
This crate shows how to generate the staticlib and use the bindgen macro and cbindgen to generate a C header for sokoban. In particular, you should note:
- The
build.rs
within the crate - The
staticlib
option specified within the[lib]
section of the Cargo.toml - The use of
use sokoban_bindgen::*
, which imports theconcat_idents
macro with a particular name
To use the example in C or Zig:
- To build the static library and header via cargo, use
cargo +nightly build --release -p sokoban-bindings-example
. Nightly is required for macro expansion. The header will be written toexamples/c/sokoban.h
.
To build and run the C example: The makefile provided will do the same thing as step 1 when make
is invoked, in addition to building the C example. The executable will be written to examples/c/sokoban.out
.
To run the Zig Example: After building the static library and header via step 1 or via make
, navigate to examples/zig and zig build run
.
-
Option<T>
is used by sokoban to communicate insertion and retrieval success and failure, but it is not FFI safe. Two valuesSUCCESS = 0
andFAILURE = u32::MAX
were introduced to deal with this1. In lieu of anOption
, these values communicates to the C or Zig application that an attempt to insert or retrieve a value failed or succeeded. As an example, for the red black tree:- Instead of
insert
returning anOption<u32>
node address which isNone
when insertion fails, the function returnsFAILURE
if it failed to insert or the node address (also au32
) if it succeeded. - Instead of
get
returning anOption<&V>
, orremove
returning anOption<V>
, the function accepts a pointer to which the value will be copied if successful, along withSUCCESS = 0
. If the retrieval fails,FAILURE = u32::MAX
is returned and the pointer remains untouched (and perhaps uninitialized!).
- Instead of
Footnotes
-
This limits the capacity of the node allocator to one less than its max value. ↩