Reputation: 6981
I found this question, but it is 3 years old and since then, crates like cxx
have come into existence. Is it possible now to construct a C++ object from Rust, or do I still have to create a shim?
Upvotes: 3
Views: 1470
Reputation: 10992
To the extent that constructors "return" a C++ type by value, they're not translatable to Rust because Rust moves (memcpy) are incompatible with C++ moves (which can require a move constructor to be called). Translating an arbitrary constructor to fn new() -> Self
would not be correct.
You can bind them unsafely with bindgen which assumes moving without a constructor call is okay, or you can use the "shared struct" approach in the readme which is safely movable in either language, or you can include!
a shim which does the construction behind a unique_ptr or similar.
That last approach would look something like:
// suppose we have a struct with constructor `ZeusClient(std::string)`
// in a C++ header:
std::unique_ptr<ZeusClient> zeus_client_new(rust::Str arg);
// in the corresponding C++ source file:
std::unique_ptr<ZeusClient> zeus_client_new(rust::Str arg) {
return make_unique<ZeusClient>(std::string(arg));
}
// in the Rust cxx bridge:
extern "C++" {
include!("path/to/zeus/client.h");
include!("path/to/constructorshim.h");
type ZeusClient;
fn zeus_client_new(arg: &str) -> UniquePtr<ZeusClient>;
}
In the future it's very likely CXX will include something builtin for this pattern, or maybe for the special case of structs without a move constructor. This is tracked in dtolnay/cxx#280.
extern "C++" {
type ZeusClient;
fn new(arg: &str) -> ZeusClient; // will verify there is no move constructor
fn new(arg: &str) -> UniquePtr<ZeusClient>; // okay even with move constructor
}
Upvotes: 6