Rust interop with C ++ std :: string

I am trying to create Octave functions in Rust. The Octave API is in C ++, so I created the bindings using rust-bindgen. I am currently working on problems that arise when trying to create bindings that include std::string . It would be nice if I could leave it an opaque and valid pointer to C ++ std::string . Is it possible to build a utility function on the C ++ side at any time when I needed to go into C ++ std::string ?

I was naive when I first tried to do this. This is clearly wrong. Rust std::ffi:CString for C strings, not C ++ strings. I found this recent blog useful when comparing the two. My first attempt looks like this :

 #![allow(non_snake_case)] #![allow(unused_variables)] extern crate octh; // https://thefullsnack.com/en/string-ffi-rust.html use std::ffi::CString; #[no_mangle] pub unsafe extern "C" fn Ghelloworld (shl: *const octh::root::octave::dynamic_library, relative: bool) -> *mut octh::root::octave_dld_function { let name = CString::new("helloworld").unwrap(); let pname = name.as_ptr() as *const octh::root::std::string; std::mem::forget(pname); let doc = CString::new("Hello World Help String").unwrap(); let pdoc = doc.as_ptr() as *const octh::root::std::string; std::mem::forget(pdoc); octh::root::octave_dld_function_create(Some(Fhelloworld), shl, pname, pdoc) } pub unsafe extern "C" fn Fhelloworld (args: *const octh::root::octave_value_list, nargout: ::std::os::raw::c_int) -> octh::root::octave_value_list { let list_ptr = ::std::ptr::null_mut(); octh::root::octave_value_list_new(list_ptr); ::std::ptr::read(list_ptr) } 

I need to pass the function name and documentation as strings to octave_dld_function_create . I'm sorry I used CppString . Any suggestions on how to proceed?

+5
source share
1 answer

This is a classic FFI problem, and the solution is to use a โ€œwatch glassโ€: Language A <=> Common ABI <=> Language B.

Of course, bindgen could be developed so that it can accurately reproduce C ++ ABI, but in practice this would require a complete C ++ compiler, which would probably be too large.

Using the hour-glass project, each language with a complex ABI uses its own specialized toolchain to convert to a specific known ABI. In this case, it will be C ++ <=> C <=> Rust.

A possible solution is to create a C wrapper library around the C ++ API, and then use bindgen. This is what LLVM and Clang do.

This is the simplest solution, and the Octavo project may well be ready to integrate such an octavo-c facade into a tree (which is always better to guarantee its relevance).


Another solution would be to create a C ++ - compatible library for bindgen, which will take care of providing C-ABI for common C ++ types (e.g. std::string ). This would be more difficult, especially since:

  • C has no generics, so C ++ templates should either be out of scope, or pre-created templates should be wrapped one at a time,
  • C does not know how to call move or copy constructors, so if C ++ types are not PODs, they need to be manipulated with opaque pointers,
  • C doesn't know ...
+3
source

Source: https://habr.com/ru/post/1272278/


All Articles