# Zngur [github](https://github.com/hkalbasi/zngur) [crates.io](https://crates.io/crates/zngur) [docs.rs](https://docs.rs/zngur) [build status](https://github.com/hkalbasi/zngur/actions?query=branch%3Amain) Zngur (/zængɑr/) is a C++/Rust interop tool. It tries to expose arbitrary Rust types, methods and functions, while preserving its semantics and ergonomics as much as possible. Using Zngur, you can use arbitrary Rust crate in your C++ code as easily as using it in normal Rust code, and you can write idiomatic Rusty API for your C++ library inside C++. See [the documentation](https://hkalbasi.github.io/zngur/) for more info. ## Demo ```C++ #include #include #include "./generated.h" // Rust values are available in the `::rust` namespace from their absolute path // in Rust template using Vec = rust::std::vec::Vec; template using Option = rust::std::option::Option; template using BoxDyn = rust::Box>; // You can implement Rust traits for your classes template class VectorIterator : public rust::std::iter::Iterator { std::vector vec; size_t pos; public: VectorIterator(std::vector &&v) : vec(v), pos(0) {} ~VectorIterator() { std::cout << "vector iterator has been destructed" << std::endl; } Option next() override { if (pos >= vec.size()) { return Option::None(); } T value = vec[pos++]; // You can construct Rust enum with fields in C++ return Option::Some(value); } }; int main() { // You can call Rust functions that return things by value, and store that // value in your stack. auto s = Vec::new_(); s.push(2); Vec::push(s, 5); s.push(7); Vec::push(s, 3); // You can call Rust functions just like normal Rust. std::cout << s.clone().into_iter().sum() << std::endl; // You can catch Rust panics as C++ exceptions try { std::cout << "s[2] = " << *s.get(2).unwrap() << std::endl; std::cout << "s[4] = " << *s.get(4).unwrap() << std::endl; } catch (rust::Panic e) { std::cout << "Rust panic happened" << std::endl; } int state = 0; // You can convert a C++ lambda into a `Box` and friends. auto f = BoxDyn>::make_box([&](int32_t x) { state += x; std::cout << "hello " << x << " " << state << "\n"; return x * 2; }); // And pass it to Rust functions that accept closures. auto x = s.into_iter().map(std::move(f)).sum(); std::cout << x << " " << state << "\n"; std::vector vec{10, 20, 60}; // You can convert a C++ type that implements `Trait` to a `Box`. // `make_box` is similar to the `make_unique`, it takes constructor arguments // and construct it inside the `Box` (instead of `unique_ptr`). auto vec_as_iter = BoxDyn>::make_box< VectorIterator>(std::move(vec)); // Then use it like a normal Rust value. auto t = vec_as_iter.collect(); // Some utilities are also provided. For example, `zngur_dbg` is the // equivalent of `dbg!` macro. zngur_dbg(t); } ``` Output: ``` 17 s[2] = 7 thread '' panicked at 'called `Option::unwrap()` on a `None` value', examples/simple/src/generated.rs:186:39 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace s[4] = Rust panic happened hello 2 2 hello 5 7 hello 7 14 hello 3 17 34 17 vector iterator has been destructed [main.cpp:71] t = [ 10, 20, 60, ] ``` See the [`examples/simple`](https://github.com/HKalbasi/zngur/blob/main/examples/simple) if you want to build and run it.