Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to safely pass a C++ string to Rust?

Tags:

c++

rust

I have this Rust function:

pub extern "C" fn do_something(my_string: &str) {
    let s = String::from(my_string);
}

That I call on C++ with this:

std::string my_string("hello");
do_something(my_string.c_str());

Signature:

extern "C" void* do_something(const char*);

I get this error right on the String::from line:

memory allocation of 127963177044160 bytes failedAborted (core dumped)

I guess that it's because the string passed has no \n so it tries to make a string of the maximum size possible.

How to safely pass a std::string to Rust?

like image 356
Guerlando OCs Avatar asked Dec 08 '22 10:12

Guerlando OCs


2 Answers

That I call on C++ with this:

do_something(my_string.c_str());

So on the C++ side you're calling a function with a C string as input (not an std::string, which is a very relevant distinction).

This means the Rust function should take a C string as input, which &str definitely isn't.

Thus do_something should be declared as:

pub extern "C" fn do_something(my_string: *const c_char) {

following which as Jmb notes you may want to use CStr in order to safely wrap the pointer.

like image 176
Masklinn Avatar answered Jan 09 '23 09:01

Masklinn


The &str type is not FFI-safe. I would expect the Rust compiler to issue a warning to that effect. Rust slices consist of a pointer and a length and do not have a layout compatible with the C++ const char*.

One option would be to have do_something accept a pointer and a length (*const u8 and usize, respectively), call std::slice::from_raw_parts to exchange those for a &'a [u8], and call std::str::from_utf8_unchecked to exchange that for a &str. You must ensure the safety conditions documented along with each of those functions are upheld, including that the string contains valid UTF-8.

like image 28
mvanbem Avatar answered Jan 09 '23 10:01

mvanbem