@Dedalus Healthcare – ATM on parental leave – Hiking fan – Mob-Programming on Open Source Software Meetup organizer – https://twitter.com/Harald3DCV (DMs are open)
• Develop application logic in Rust – Develop e.g. UI in Gtk/C or Qt/C++ • Incrementally modernize a codebase • Priority queue (aka std::collections::BinaryHeap) – Put elements out of order – Pop elements in sorted order • Build a foreign function interface (FFI) module
guarantees do not hold across FFI boundaries • Rust mangles function names – #[no_mangle] • Rust does not follow the C (or platform) calling convention – extern “C” or extern “system” • Some Rust types are not “ffi-safe” – Slices & tagged enums don’t have a C equivalent • Structs & enums with the Rust repr don’t have specified layouts – #[repr(C)]
mut pqueue = PQueueU8(std::collections::BinaryHeap::new()); for &element in elements { pqueue.0.push(element); } Box::new(pqueue) } impl PQueueU8 { fn pop(&mut self) -> Result<u8, &'static str> { self.0.pop().ok_or("queue is empty") } } C++ bindings using cxx – Implementation The error type
build $ ls target/cxxbridge/pqueue/src lib.rs.cc lib.rs.h $ c++ -Wall -Werror target/release/libpqueue.a -o pqueue_test $ valgrind ./pqueue_test … 5 4 2 2 1 pop error: queue is empty pop error: queue is empty pop error: queue is empty pop error: queue is empty pop error: queue is empty … ==16054== ==16054== HEAP SUMMARY: ==16054== in use at exit: 0 bytes in 0 blocks ==16054== total heap usage: 20 allocs, 20 frees, 74,596 bytes allocated ==16054== ==16054== All heap blocks were freed -- no leaks are possible ==16054== ==16054== For lists of detected and suppressed errors, rerun with: -s ==16054== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) # Cargo.toml … [lib] crate-type = ["staticlib", "cdylib"] … [dependencies] cxx = "1.0" … [build-dependencies] cxx-build = "1.0" … + build.rs
array memory! BUT might block Java GC until the AutoPrimitiveArray is destroyed (= end of critical section) https://www.ibm.com/docs/en/sdk-java-technology/8?topic=jni-copying-pinning
{ System.loadLibrary("pqueue_jni"); } private long objPtr; public RustyPriorityQueue(byte[] elements) {} } Needs to be a shared (dynamic) library (.dll/.so)! crate-type = ["cdylib"]
but slow (interesting if speed is not important) • Java Native Runtime (JNR-FFI) – Comparable performance to JNI without the hand-written glue code • Project Panama (still experimental) • Rule of thumb: Also consider the performance penalty of the interface when going native
code using the cxx crate • Without reviewing generated header files • And without maintaining C++ wrappers over a C API # Cargo.toml … [lib] crate-type = ["staticlib", "cdylib"] … [dependencies] cxx = "1.0" … [build-dependencies] cxx-build = "1.0" …
mut pqueue = PQueueU8(std::collections::BinaryHeap::new()); for &element in elements { pqueue.0.push(element); } Box::new(pqueue) } C++ bindings using cxx A slice!