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.47k stars 698 forks source link

C++ std::function types are translated into [u128; 3usize] #1724

Open mayabyte opened 4 years ago

mayabyte commented 4 years ago

header.hpp:

using example_type = std::function<void()>;

bindgen invocation:

let bindings = bindgen::Builder::default()
        .header("header.hpp")
        .opaque_type("std::.*")
        .whitelist_type("example_type")
        .rust_target(bindgen::RustTarget::Nightly)
        .parse_callbacks(Box::new(bindgen::CargoCallbacks))
        .generate()
        .expect("Unable to generate bindings");

Output binding:

pub type example_type = [u128; 3usize];

With just a plain typedef like this all is well, but in many situations bindgen also needs to use this type (possibly indirectly) in an extern "C" {...} block, resulting in warnings like this:

warning: `extern` block uses type `[u128; 3usize]`, which is not FFI-safe
    --> src/../bindings.rs:9772:18
     |
9772 |             root::example_type;
     |             ^^^^^^^^^^^^^^^^^^ not FFI-safe
     |
     = help: consider passing a pointer to the array
     = note: passing raw arrays by value is not FFI-safe

warning: `extern` block uses type `u128`, which is not FFI-safe
    --> src/../bindings.rs:1230:27
     |
1230 |                     this: *const root::example_type,
     |                           ^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
     |
     = note: 128-bit integers don't currently have a known stable ABI

While not strictly an error, it makes me uneasy that function pointers may or may not be interpreted correctly between the C++ library I need to use and my own code.

Is there a way to get bindgen to generate, say, &[u64; 6usize] or something for std::functions instead? Is this intended behavior or unexpected?

I have a feeling this could be related to the use of .opaque_type("std::.*"), but whitelisting std::function doesn't seem to change anything and I'd greatly prefer not to generate bindings for all of std.

emilio commented 4 years ago

Yes, this is what opaque_type causes when used on this kind of stuff... That being said, it seems to me it's a rust bug to complain that *const root::example_type is not FFI-safe...

elichai commented 4 years ago

That being said, it seems to me it's a rust bug to complain that *const root::example_type is not FFI-safe...

https://github.com/rust-lang/rust/issues/66220 Enjoy :)

thomaseizinger commented 3 years ago

Out of curiosity, why is this mapping happening? Does this array represent multiple pointers (context, parameters and return value?) or what does it mean semantically?

jschwe commented 3 months ago

Out of curiosity, why is this mapping happening?

This related issue https://github.com/rust-lang/rust-bindgen/issues/2071#issuecomment-882329820 states that basically the example_type should not be translated by bindgen, but since bindgen does it anyway, the user should blocklist it manually.