rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
98.63k stars 12.74k forks source link

Add a bindgen pass #2124

Closed brson closed 9 years ago

brson commented 12 years ago

Make a pass that executes bindgen during the build.

This would build the jsapi module automatically based on the header files:

#[bindgen(files("jsapi.h", "jswhatever.h"), name = "jsapi")];

It would never generate any .rs files, just insert it directly into the AST.

catamorphism commented 11 years ago

Rather than baking this in as a syntax extension, I think this could be a good test for rustpkg's custom build logic. As such, it's blocked on #5677.

emberian commented 11 years ago

Still relevant

catamorphism commented 11 years ago

The major sub-bugs of #5677 are done, so this is ready to work on.

huonw commented 10 years ago

cc #10530 (the converse operation; generating a C header from a Rust file), and some keywords (since I couldn't find this issue when opening that one): C header, C library, libclang, clang.

thestinger commented 10 years ago

I'm nominating this because I think hard-wiring the ABI of C libraries is a huge problem. Rust libraries are going to silently fail across library versions with breaking changes to the ABI. If we had this, using C from Rust would be as easy as from C++. It would be a killer feature of the language in my opinion.

I don't think it would be incredibly difficult to move bindgen into the Rust compiler proper and start hooking it up to resolve.

emberian commented 10 years ago

I agree.

metajack commented 10 years ago

In theory this sounds great. How do you deal with unions? Will the bindgen do the right thing with * vs. *mut? Servo basically uses bindgen as an initial thing just so we don't have to type everything, but it doesn't seem capable of generating the final bindings in all cases.

Not to mention that you can't handle C macros, which must be shimmed.

huonw commented 10 years ago

How do you deal with unions?

rust-bindgen currently converts

union Foo {
  int x;
  char y;
  double z;
};

into

use std::libc::*;
pub struct Union_Foo {
    data: [u64, ..1u],
}
impl Union_Foo {
    pub fn x(&mut self) -> *mut c_int {
        unsafe { ::std::cast::transmute(::std::ptr::to_mut_unsafe_ptr(self)) }
    }
    pub fn y(&mut self) -> *mut c_schar {
        unsafe { ::std::cast::transmute(::std::ptr::to_mut_unsafe_ptr(self)) }
    }
    pub fn z(&mut self) -> *mut c_double {
        unsafe { ::std::cast::transmute(::std::ptr::to_mut_unsafe_ptr(self)) }
    }
}

Of course, if it were built into the compiler we could have first class FFI unions.

Will the bindgen do the right thing with * vs. *mut?

If the C headers are const-correct, I believe it does approximately the right thing.

Not to mention that you can't handle C macros, which must be shimmed.

We can do a best effort thing, aiui libclang offers sensible handling of macros (I don't know the details).

thestinger commented 10 years ago

@metajack: A basic implementation will remove 100% of the ABI hard-wiring for libraries designed with FFI in mind like sqlite3 and libgit2. It's true that it will never be perfect for many libraries, but it will certainly vastly reduce the redundancy on the Rust side and therefore the risk of silent breakage with different versions or even configurations of the library.

pnkfelix commented 10 years ago

Not as high a priority as it seemed 2 years ago. P-low.

huonw commented 10 years ago

This could probably be done as an loadable syntax extension now that we have them, e.g.

#[phase(syntax)] extern crate bindgen;

#[bindgen("foo.h")] // fills the module with the appropriate `extern` block
mod foo {}
ghost commented 10 years ago

Vala does this correctly. Of course they cheat by compiling to C, but the interface is nice.

brson commented 9 years ago

I don't feel as passionately abut integrating a C compiler into our Rust compiler any more. It doesn't feel very pressing, can probably done out-of-tree through Cargo eventually. Closing but feel free to reopen if you disagree.