Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Returning CxxString from Rust to C++ #1339

Open
FireFragment opened this issue Apr 6, 2024 · 5 comments
Open

Returning CxxString from Rust to C++ #1339

FireFragment opened this issue Apr 6, 2024 · 5 comments

Comments

@FireFragment
Copy link

FireFragment commented Apr 6, 2024

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.

@zambony
Copy link

zambony commented May 1, 2024

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.

@FireFragment
Copy link
Author

Thanks @zambony! That's a fine option when returning a single string, but it doesn't work well for strings inside classes/structs.

@izolyomi
Copy link

I've also just encountered this issue. Are there any updates to do this properly instead of using out parameters?

@FireFragment
Copy link
Author

FireFragment commented Jul 22, 2024

@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.

@izolyomi
Copy link

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants