Interfacing Rust with C and C++


#1

Hello, world. Brand new poster here though I posted similar messages in other language forums. I hope this is the right place to ask because my question is half about existing stuff and half about prospective work.

I am considering starting with Rust amid a C++ code base. New Rust code would need to somehow integrate with the existing C++ code. The C++ code is the expected melange of free functions, classes, what have you and uses STL and Boost (also other libs less prominently). Allow me to ask:

  1. What is the current support for calling C/C++ free functions from Rust? What level of mangling is supported? What data types can be passed without translation from Rust to C/C++?

  2. How about template functions? Is it possible to call a C++ template function from Rust?

  3. How can a C++ object be used from Rust? Can C++ methods be called from Rust? The question applies to value types - no virtuals - and polymorphic types with virtuals, inheritance etc. And of course simple C structs.

  4. How about template objects? One issue is that many C++ interfaces pass std::string and std::map<…, …> as parameters. How feasible is to manipulate such objects in Rust?

  5. How about the other way? Can a C/C++ function call a Rust function?

I would appreciate any pointers you have to how-to materials. In equal measure I am interested in plans to address such issues in the foreseeable future. Thankyou.

Scott


#2
  1. The current state of calling C/C++ functions is that you can only call C functions, C++ functions need an extern "C" wrapper.
  2. (See 1.) The template functions would need to be instantiated by the C++ code in an extern "C" block.
  3. Again, one needs to wrap the methods in extern "C" functions taking a pointer to the object and the rest of the parameters. Structs and classes can be described by #[repr(C)] structs if I remember correctly (not sure about this one).
  4. You probably need to wrap each instantiation in extern "C" functions and instantiate all template classes as #[repr(C)] structs.
  5. You can create extern "C" {} blocks with #[no_mangle] in which the Rust functions can be called by C/C++ or just any code that can call into the C calling convention.

All in all, this means that calling C is properly supported by Rust, calling C++ is not, but can be emulated by the ability to call C functions.

The reason stated why C++ is not properly supported is that one apparantly needs a C++ compiler to actually be able to call into C++.


#3

BTW, discuss.rust-lang.org is trying to be focused on language and (standard) library design discussions; questions like these are better suited to Stack Overflow or /r/rust.


#4

Many thanks @tbu. I looked for #[repr©] and found http://doc.rust-lang.org/guide-ffi.html. Which I have perused leading to additional questions.

Contiguous buffers and lengths can be passed portably. For example

fn snappy_validate_compressed_buffer(
  compressed: *const u8,
  compressed_length: size_t) -> c_int

Is there a way short of writing a wrapper to explain the type system that the two parameters are interdependent?

How about passing a Rust string to a C function expecting a zero-terminated string? More importantly I am concerned with passing more complex structures such as hash tables across the languages. It seems some marshaling is needed, is there a standard mechanism for marshaling?

A full C++ compiler should not be needed for proper name mangling and ABI. Are there any plans for the Rust designers to enhance C++ support in Rust? (@huon that’s why I asked here. I am interested in future outlook as much as what is available right now.)


#5

You can write a wrapper

fn snappy_validate_buffer(compressed: &[u8]) -> c_int {
    unsafe { raw::snappy_validate_buffer(compressed.as_ptr(), compressed.len() }
}

There’s a struct CStr for dealing with this.

You should probably just expose the interface functions in either language as extern "C".

I don’t know the specifics there, try to look over github or so.


#6

http://doc.rust-lang.org/master/std/c_str/struct.CString.html

I still recommend either of those two venues since these are general questions not language/library work (and yes, many/most of the key Rust developers hang out on /r/rust :slight_smile: ); we try to keep this forum focused on proposals/development work, since we have other venues appropriate for questions. Furthermore, questions very similar to this have been asked recently, example.

At the very least, it’s a good idea to scout out the current state of Rust’s support by asking on /r/rust, and then digest that into focused ‘future work’ questions which may be more appropriate for here. :slight_smile:


#7

You can at least still pass references to abstractions like Vec’s/std::vectors with extern “C” functions (extern “C” used in C++ code) so its not a completely lost cause. you can roll C++ equivalents of rust abstractions, and viva versa.

I wonder if it would be theoretically possible to ask both C++ and Rust to instantiate tempted functions for specific types, making them available as overloaded functions using a C++ name mangling scheme (i realise thats’ compiler specific)