rust-lang / rust-bindgen

Automatically generates Rust FFI bindings to C (and some C++) libraries.
https://rust-lang.github.io/rust-bindgen/
BSD 3-Clause "New" or "Revised" License
4.46k stars 696 forks source link

Better support for well-known C++ types #738

Open jcranmer opened 7 years ago

jcranmer commented 7 years ago

Certain types like std::string or std::vector are quite common in C++ code, yet trying to run them through bindgen tends to be a nightmare because their implementations are actually very complicated. There are also types like string_view or llvm::StringRef that are conceptually identical to native Rust types (&str, in this case, sidestepping the issue of UTF-8/non-UTF-8) that would be useful to have represented as the native Rust type in function calls.

Rather than trying to work towards getting all the functionality necessary to build std::string (which is really a complex template that no one uses as such), it makes sense to provide a dedicated mapping mechanism specifically for the std::string type. This could perhaps be done by giving a mechanism to say "where you see type T as a function parameter in C/C++, use RustTy instead for the Rust code" and providing code to map between the C++ and Rust types.

dmilith commented 5 years ago

I lost last few days trying to read a freaking C++ function returning std::string… to use it from Rust side… STL is a hellhole of complexity… and I've failed :( When I use const char* instead.. it's leaking memory like a dog…

jeffvandyke commented 5 years ago

We have a case where, when interacting with Windows, std::wstring was useful, so it might be good to keep in mind other string types besides std::string, but an easy-to-use mapping from C++'s std::string to Rust's std::string::String would handle many cases.

This, of course, is part of a bigger problem of easier mapping to STL types (like std::vector, std::map, and perhaps other non-collection types), to which a consistent solution for the individual types would probably make interop with C++ easier for everyone

jonhoo commented 5 years ago

I'm curious -- what is currently the way to work around issues that arise around these types? For example, I'm currently struggling with a header file that ends up with a #include "string_view.hpp" (this file specifically), and it causes bindgen to choke with

[2019-11-13T00:08:29Z DEBUG bindgen::ir::context] BindgenContext::add_item(Item { id: ItemId(95897), local_id: Cell { value: None }, next_child_local_id: Cell { value: 1 }, canonical_name_cache: RefCell { value: None }, comment: None, annotations: Annotations { opaque: false, hide: false, use_instead_of: None, disallow_copy: false, private_fields: None, accessor_kind: None, constify_enum_variant: false, derives: [] }, parent_id: ItemId(95824), kind: Type(Type { name: Some("u32string_view"), layout: Some(Layout { size: 16, align: 8, packed: false }), kind: Alias(TypeId(ItemId(95898))), is_const: false }) }, declaration: Some(Cursor(u32string_view kind: TypedefDecl, loc: external/plasma/cpp/src/arrow/vendored/string_view.hpp:1143:38, usr: Some("c:string_view.hpp@N@nonstd@N@sv_lite@T@u32string_view"))), loc: Some(Cursor(u32string_view kind: TypedefDecl, loc: external/plasma/cpp/src/arrow/vendored/string_view.hpp:1143:38, usr: Some("c:string_view.hpp@N@nonstd@N@sv_lite@T@u32string_view")))
[2019-11-13T00:08:29Z DEBUG bindgen::ir::context] add_item_to_module: adding ItemId(95897) as child of parent module ItemId(95824)
thread 'main' panicked at 'Unknown token while processing namespace: ClangToken { spelling: CXString { data: 0x55d7af5201f0, private_flags: 1 }, kind: 0 }', /home/jon/.cargo/registry/src/github.com-1ecc6299db9ec823/bindgen-0.51.1/src/ir/context.rs:2164:21

How do I work around this? Marking the type as opaque won't actually prevent bindgen from trying to parse the include file it seems.

Volker-Weissmann commented 4 years ago

What is the currently recommended way to call a c++ function that wants a std::string argument from rust?

auscompgeek commented 4 years ago

What is the currently recommended way to call a c++ function that wants a std::string argument from rust?

Two options I'm aware of:

adetaylor commented 4 years ago

I am about to embark on an endeavor to adjust a fork of bindgen to output a #[cxx::bridge] section as required by the cxx crate, instead of plain Rust. The idea is to provide just the sort of thing described here — passing standard C++ types safely between C++ and Rust, generating suitable binding code on both sides, based on declarations and definitions in existing C++ headers.

If this works out (even a little bit) I'll discuss how/whether these changes can be submitted to bindgen or if they should forever live in a fork, or if bindgen can be made modular in some way to support this. There's a bit of discussion on this plan here.

This will be not be a high priority project for me, so expect not to hear anything for months. But if anyone wants to collaborate, please get in touch!

barakugav commented 4 months ago

I would really appreciate a support for std::vector<T>. Maybe im missing something but I can't get it to work, does anyone have a working solution?