Rust code can call (non-member) functions defined in C++, provided that the parameter and return types are supported by Crubit:
Additionally, code can call member functions defined in C++ if the parameter and return types are supported by Crubit (see above). Non-static member functions become Rust methods, and static member functions become associated functions.
Given the following C++ header:
cs/file:examples/cpp/function/example.h function:add_two_integers
Crubit will generate the following bindings, with a safe public function that calls into the corresponding FFI glue:
cs/file:examples/cpp/function/example_generated.rs function:add_two_integers
Which can be used like this:
cs/file:examples/cpp/function/main.rs function:main
Given the following C++ header:
cs/file:examples/cpp/method/example.h class:Bar
Crubit will generate the following bindings:
cs/file:examples/cpp/method/example_generated.rs class:Bar
cs/file:examples/cpp/method/example_generated.rs content:"(?m)impl Bar.*?(^$|^ \})"
Which can be used like this:
cs/file:examples/cpp/method/main.rs function:main
The this parameter of a method becomes &self or &mut self. See References and lifetimes for more details.
unsafe functionsunsafe in Rust?By default, the Rust binding to a C++ function is marked as safe or unsafe based on the types of its parameters. If a C++ function accepts only simple types like integers, the resulting Rust binding will be marked as safe. Functions which accept a raw pointer are automatically marked as unsafe.
This behavior can be overridden using the CRUBIT_UNSAFE, CRUBIT_UNSAFE_MARK_SAFE and CRUBIT_OVERRIDE_UNSAFE(is_unsafe) macros.
For example, given the following C++ header:
cs/file:examples/cpp/unsafe_attributes/example.h content:^([^/#\n])[^\n]*
Crubit will generate the following bindings:
cs/file:examples/cpp/unsafe_attributes/example_generated.rs content:^([^/\n])([^!\n]|$)[^\n]*
Which can be used like this:
cs/file:examples/cpp/unsafe_attributes/main.rs function:main
unsafeFunctions marked unsafe cannot be called outside of an unsafe block. In order to avoid undefined behavior when using unsafe, callers must:
Ensure that the pointer being passed to C++ is a valid C++ pointer. In particular, it must not be dangling (e.g. Nonnull::dangling()).
Ensure that the safety conditions documented in C++ are upheld. For example, if the C++ function accepts a reference or non-null pointer, then do not pass in 0 as *const _.
Note that many “safe” C++ functions may still trigger undefined behavior if used incorrectly. Regardless of whether a C++ function is marked as unsafe, calls into C++ will only be memory-safe if the caller verifies that all function preconditions are met.
pub(crate)By default, bindings for C++ functions and methods are generated with pub visibility in Rust.
You can restrict the visibility of a function or method to the generated crate using CRUBIT_PUB_CRATE from "support/annotations.h":
#include "support/annotations.h" CRUBIT_PUB_CRATE void HelperFunction(); class MyClass { public: CRUBIT_PUB_CRATE void InternalMethod(); };
This is especially useful when providing handwritten Rust APIs via the srcs attribute of rust_api_from_cpp (see Best Practices). The custom Rust code in srcs can call the pub(crate) functions or methods, while keeping them hidden from downstream crates.
CRUBIT_PUB_CRATE is only valid on functions and methods; applying it to types will produce an error.
Most function attributes are not supported. For example, functions marked [[noreturn]] don't get bindings. [[nodiscard]] is supported and becomes #[must_use].