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.42k stars 694 forks source link

Define macro type aliases / Custom macro parsing in special use cases #1754

Open agausmann opened 4 years ago

agausmann commented 4 years ago

In working on emscripten-sys, I have a scenario where #define macros are being used as type aliases, which I would like to translate to Rust.

Since I don't think this is a very common pattern, if you don't wish to merge this upstream, I think it could be resolved by somehow allowing the callee to specify custom behavior via ParseCallbacks for macros that bindgen doesn't know how to handle.

Input C/C++ Header

types.h:

#define EMSCRIPTEN_RESULT int

Bindgen Invocation

fn main() {
    let builder = bindgen::builder()
        .header("types.h");

    builder
        .generate()
        .expect("failed to generate rust bindings")
        .write(Box::new(std::io::stdout()))
        .expect("failed to write to file");
}

Actual Results

No bindings are generated.

Expected Results

pub type EMSCRIPTEN_RESULT = c_int;
emilio commented 4 years ago

Yeah the problem with doing this automatically is that you literally can't. C macros are pretty bad at this kind of thing... Maybe we should add a macro which would generate arbitrary code? But then I guess that users of that macro would use c_int instead of EMSCRIPTEN_RESULT...

agausmann commented 4 years ago

Yes, for arbitrary types it's pretty much impossible, but if it were limited to primitives (those in std::os::raw, plus pointers maybe), or if it were implemented by users themselves who have full knowledge of the library, it would be possible.

emilio commented 4 years ago

Even for simple types, you don't really know what the type is without actually expanding the macro.