5个版本 (3个重大更改)

0.4.0 2023年10月10日
0.3.0 2023年10月6日
0.2.2 2023年10月5日
0.2.1 2023年9月25日
0.0.3 2023年9月1日

#1594 in Rust模式

Download history 1/week @ 2024-03-07 1/week @ 2024-03-14 14/week @ 2024-03-28 8/week @ 2024-04-04 3/week @ 2024-04-25 65/week @ 2024-05-02

每月52次下载
用于 zngur-cli

MIT/Apache

105KB
2.5K SLoC

Zngur

github crates.io docs.rs build status

Zngur (/zēngɑr/) 是一个 C++/Rust 互操作性工具。它尝试尽可能多地暴露任意 Rust 类型、方法和函数,同时保留其语义和易用性。使用 Zngur,您可以在 C++ 代码中使用任意 Rust crate,就像在常规 Rust 代码中使用它一样,您还可以在 C++ 中编写 Rusty API,以供您的 C++ 库使用。有关更多信息,请参阅文档

演示

#include <iostream>
#include <vector>

#include "./generated.h"

// Rust values are available in the `::rust` namespace from their absolute path
// in Rust
template <typename T> using Vec = rust::std::vec::Vec<T>;
template <typename T> using Option = rust::std::option::Option<T>;
template <typename T> using BoxDyn = rust::Box<rust::Dyn<T>>;

// You can implement Rust traits for your classes
template <typename T>
class VectorIterator : public rust::std::iter::Iterator<T> {
  std::vector<T> vec;
  size_t pos;

public:
  VectorIterator(std::vector<T> &&v) : vec(v), pos(0) {}
  ~VectorIterator() {
    std::cout << "vector iterator has been destructed" << std::endl;
  }

  Option<T> next() override {
    if (pos >= vec.size()) {
      return Option<T>::None();
    }
    T value = vec[pos++];
    // You can construct Rust enum with fields in C++
    return Option<T>::Some(value);
  }
};

int main() {
  // You can call Rust functions that return things by value, and store that
  // value in your stack.
  auto s = Vec<int32_t>::new_();
  s.push(2);
  Vec<int32_t>::push(s, 5);
  s.push(7);
  Vec<int32_t>::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<dyn Fn>` and friends.
  auto f = BoxDyn<rust::Fn<int32_t, int32_t>>::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<int32_t> vec{10, 20, 60};
  // You can convert a C++ type that implements `Trait` to a `Box<dyn Trait>`.
  // `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<rust::std::iter::Iterator<int32_t>>::make_box<
      VectorIterator<int32_t>>(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);
}

输出

17
s[2] = 7
thread '<unnamed>' 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,
]

如果您想构建和运行它,请参阅examples/simple

依赖关系

~3.5MB
~48K SLoC