cxx
cxx copied to clipboard
Returning `CxxString` from Rust to C++
Is it possible to construct CxxString on the Rust side and return it to the C++ side?
Returning Pin<&mut CxxString> doesn't work, because it's just a reference to local variable, which is destroyed at the end of the function:
fn hello<'a>() -> std::pin::Pin<&'a mut CxxString> {
let_cxx_string!(name = "Hello from Rust string!");
name // ERROR: returns a value referencing data owned by the current function
}
Returning UniquePtr<CxxString> doesn't work, because I'm not able to construct it:
fn hello2<'a>() -> cxx::UniquePtr<CxxString> {
let_cxx_string!(name = "Hello from Rust string!");
cxx::UniquePtr::new(*name) // ERROR: type mismatch resolving `<CxxString as ExternType>::Kind == Trivial`
// expected `Trivial`, found `Opaque`
}
How can I do it? I want my generated bindings to use standard C++ structs such as std::string without needing the C++ users to deal with rust::String which they might not know and might not work with other C++ libraries.
In case you're still trying to do this, I wanted to do something similar, but I don't think it's possible. What I ended up doing instead is used an out parameter.
#[cxx::bridge(namespace = "rs")]
mod ffi {
extern "Rust" {
fn ask(response: Pin<&mut CxxString>);
}
}
pub fn ask(response: Pin<&mut CxxString>) {
response.push_str("Hi!!!");
}
It would be nice to return stack-allocated C++ types, though.
Thanks @zambony! That's a fine option when returning a single string, but it doesn't work well for strings inside classes/structs.
I've also just encountered this issue. Are there any updates to do this properly instead of using out parameters?
@izolyomi: I've also just encountered this issue. Are there any updates to do this properly instead of using out parameters?
I managed to get around this by creating function on the C++ side for constructing new empty string and writing to it on the Rust side.
Rust:
fn str_test() -> UniquePtr<CxxString> {
let mut s = ffi::get_empty_string();
s.pin_mut().push_str("Hello from str_test");
s
}
C++:
#include <string>
#include <memory>
std::unique_ptr<std::string> get_empty_string() {
return std::make_unique<std::string>(std::string(""));
}
But this should really be supported by the library.
Thank you for the detailed example. So far I was exposing Rust to C++ but had nothing in the other direction yet. I'll consider if using output parameters with C++ string, returning Rust string or involving a C++ utility function is better in my case.