diff options
-rw-r--r-- | src/clang.rs | 13 | ||||
-rw-r--r-- | src/codegen/mod.rs | 10 | ||||
-rw-r--r-- | src/ir/context.rs | 2 | ||||
-rw-r--r-- | src/ir/function.rs | 3 | ||||
-rw-r--r-- | src/lib.rs | 30 | ||||
-rw-r--r-- | src/options.rs | 7 | ||||
-rw-r--r-- | tests/expectations/tests/enum_and_vtable_mangling.rs | 4 | ||||
-rw-r--r-- | tests/expectations/tests/generate-inline.rs | 33 | ||||
-rw-r--r-- | tests/expectations/tests/nested_vtable.rs | 4 | ||||
-rw-r--r-- | tests/expectations/tests/ref_argument_array.rs | 4 | ||||
-rw-r--r-- | tests/expectations/tests/virtual_dtor.rs | 4 | ||||
-rw-r--r-- | tests/expectations/tests/virtual_inheritance.rs | 8 | ||||
-rw-r--r-- | tests/expectations/tests/virtual_overloaded.rs | 4 | ||||
-rw-r--r-- | tests/expectations/tests/vtable_recursive_sig.rs | 4 | ||||
-rw-r--r-- | tests/headers/generate-inline.hpp | 12 | ||||
-rw-r--r-- | tests/tests.rs | 18 |
16 files changed, 126 insertions, 34 deletions
diff --git a/src/clang.rs b/src/clang.rs index 669db207..2dbe5e51 100644 --- a/src/clang.rs +++ b/src/clang.rs @@ -1429,7 +1429,9 @@ impl Drop for Diagnostic { /// A file which has not been saved to disk. pub struct UnsavedFile { x: CXUnsavedFile, - name: CString, + /// The name of the unsaved file. Kept here to avoid leaving dangling pointers in + /// `CXUnsavedFile`. + pub name: CString, contents: CString, } @@ -1451,6 +1453,15 @@ impl UnsavedFile { } } +impl fmt::Debug for UnsavedFile { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, + "UnsavedFile(name: {:?}, contents: {:?})", + self.name, + self.contents) + } +} + /// Convert a cursor kind into a static string. pub fn kind_to_str(x: CXCursorKind) -> String { unsafe { cxstring_into_string(clang_getCursorKindSpelling(x)) } diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 7db083e7..fb6c839d 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -706,17 +706,15 @@ impl<'a> CodeGenerator for Vtable<'a> { assert_eq!(item.id(), self.item_id); // For now, generate an empty struct, later we should generate function // pointers and whatnot. - let mut attributes = vec![attributes::repr("C")]; - - if ctx.options().derive_default { - attributes.push(attributes::derives(&["Default"])) - } + let attributes = vec![attributes::repr("C")]; let vtable = aster::AstBuilder::new() .item() .pub_() .with_attrs(attributes) - .struct_(self.canonical_name(ctx)) + .tuple_struct(self.canonical_name(ctx)) + .field() + .build_ty(helpers::ast_ty::raw_type(ctx, "c_void")) .build(); result.push(vtable); } diff --git a/src/ir/context.rs b/src/ir/context.rs index 4a6785b1..c95d5179 100644 --- a/src/ir/context.rs +++ b/src/ir/context.rs @@ -182,7 +182,7 @@ impl<'ctx> BindgenContext<'ctx> { clang::TranslationUnit::parse(&index, "", &options.clang_args, - &[], + &options.input_unsaved_files, parse_options) .expect("TranslationUnit::parse failed"); diff --git a/src/ir/function.rs b/src/ir/function.rs index 941694ff..fd88b657 100644 --- a/src/ir/function.rs +++ b/src/ir/function.rs @@ -310,7 +310,8 @@ impl ClangSubItemParser for Function { return Err(ParseError::Continue); } - if cursor.is_inlined_function() { + if !context.options().generate_inline_functions && + cursor.is_inlined_function() { return Err(ParseError::Continue); } @@ -175,6 +175,14 @@ impl Builder { self } + /// Add `contents` as an input C/C++ header named `name`. + /// + /// The file `name` will be added to the clang arguments. + pub fn header_contents(mut self, name: &str, contents: &str) -> Builder { + self.options.input_unsaved_files.push(clang::UnsavedFile::new(name, contents)); + self + } + /// Set the output graphviz file. pub fn emit_ir_graphviz<T: Into<String>>(mut self, path: T) -> Builder { let path = path.into(); @@ -415,6 +423,16 @@ impl Builder { self } + /// Whether inline functions should be generated or not. + /// + /// Note that they will usually not work. However you can use + /// `-fkeep-inline-functions` or `-fno-inline-functions` if you are + /// responsible of compiling the library to make them callable. + pub fn generate_inline_functions(mut self, doit: bool) -> Self { + self.options.generate_inline_functions = doit; + self + } + /// Ignore functions. pub fn ignore_functions(mut self) -> Builder { self.options.codegen_config.functions = false; @@ -563,6 +581,9 @@ pub struct BindgenOptions { /// The input header file. pub input_header: Option<String>, + /// Unsaved files for input. + pub input_unsaved_files: Vec<clang::UnsavedFile>, + /// Generate a dummy C/C++ file that includes the header and has dummy uses /// of all types defined therein. See the `uses` module for more. pub dummy_uses: Option<String>, @@ -584,6 +605,9 @@ pub struct BindgenOptions { /// documentation for more details. pub generate_comments: bool, + /// Whether to generate inline functions. Defaults to false. + pub generate_inline_functions: bool, + /// Wether to whitelist types recursively. Defaults to true. pub whitelist_recursively: bool, @@ -649,11 +673,13 @@ impl Default for BindgenOptions { raw_lines: vec![], clang_args: vec![], input_header: None, + input_unsaved_files: vec![], dummy_uses: None, parse_callbacks: None, codegen_config: CodegenConfig::all(), conservative_inline_namespaces: false, generate_comments: true, + generate_inline_functions: false, whitelist_recursively: true, objc_extern_crate: false, enable_mangling: true, @@ -740,6 +766,10 @@ impl<'ctx> Bindings<'ctx> { options.clang_args.push(h.clone()) } + for f in options.input_unsaved_files.iter() { + options.clang_args.push(f.name.to_str().unwrap().to_owned()) + } + let mut context = BindgenContext::new(options); try!(parse(&mut context)); diff --git a/src/options.rs b/src/options.rs index 15146b39..f1c8479a 100644 --- a/src/options.rs +++ b/src/options.rs @@ -177,6 +177,9 @@ pub fn builder_from_flags<I> .takes_value(true) .multiple(true) .number_of_values(1), + Arg::with_name("generate-inline-functions") + .long("generate-inline-functions") + .help("Whether inline functions should be generated."), Arg::with_name("whitelist-type") .long("whitelist-type") .help("Whitelist the type. Other non-whitelisted types will \ @@ -357,6 +360,10 @@ pub fn builder_from_flags<I> builder = builder.conservative_inline_namespaces(); } + if matches.is_present("generate-inline-functions") { + builder = builder.generate_inline_functions(true); + } + if let Some(whitelist) = matches.values_of("whitelist-function") { for regex in whitelist { builder = builder.whitelisted_function(regex); diff --git a/tests/expectations/tests/enum_and_vtable_mangling.rs b/tests/expectations/tests/enum_and_vtable_mangling.rs index 300edd39..b34e217f 100644 --- a/tests/expectations/tests/enum_and_vtable_mangling.rs +++ b/tests/expectations/tests/enum_and_vtable_mangling.rs @@ -10,9 +10,7 @@ pub const whatever_else: _bindgen_ty_1 = _bindgen_ty_1::whatever_else; #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub enum _bindgen_ty_1 { match_ = 0, whatever_else = 1, } #[repr(C)] -#[derive(Default)] -pub struct C__bindgen_vtable { -} +pub struct C__bindgen_vtable(::std::os::raw::c_void); #[repr(C)] #[derive(Debug, Copy)] pub struct C { diff --git a/tests/expectations/tests/generate-inline.rs b/tests/expectations/tests/generate-inline.rs new file mode 100644 index 00000000..72057414 --- /dev/null +++ b/tests/expectations/tests/generate-inline.rs @@ -0,0 +1,33 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug, Default, Copy)] +pub struct Foo { + pub _address: u8, +} +#[test] +fn bindgen_test_layout_Foo() { + assert_eq!(::std::mem::size_of::<Foo>() , 1usize , concat ! ( + "Size of: " , stringify ! ( Foo ) )); + assert_eq! (::std::mem::align_of::<Foo>() , 1usize , concat ! ( + "Alignment of " , stringify ! ( Foo ) )); +} +extern "C" { + #[link_name = "_ZN3Foo3barEv"] + pub fn Foo_bar() -> ::std::os::raw::c_int; +} +impl Clone for Foo { + fn clone(&self) -> Self { *self } +} +impl Foo { + #[inline] + pub unsafe fn bar() -> ::std::os::raw::c_int { Foo_bar() } +} +extern "C" { + #[link_name = "_Z3foov"] + pub fn foo() -> ::std::os::raw::c_int; +} diff --git a/tests/expectations/tests/nested_vtable.rs b/tests/expectations/tests/nested_vtable.rs index e16a23d7..4c9dc8f6 100644 --- a/tests/expectations/tests/nested_vtable.rs +++ b/tests/expectations/tests/nested_vtable.rs @@ -5,9 +5,7 @@ #[repr(C)] -#[derive(Default)] -pub struct nsISupports__bindgen_vtable { -} +pub struct nsISupports__bindgen_vtable(::std::os::raw::c_void); #[repr(C)] #[derive(Debug, Copy)] pub struct nsISupports { diff --git a/tests/expectations/tests/ref_argument_array.rs b/tests/expectations/tests/ref_argument_array.rs index 714467f6..51531824 100644 --- a/tests/expectations/tests/ref_argument_array.rs +++ b/tests/expectations/tests/ref_argument_array.rs @@ -6,9 +6,7 @@ pub const NSID_LENGTH: ::std::os::raw::c_uint = 10; #[repr(C)] -#[derive(Default)] -pub struct nsID__bindgen_vtable { -} +pub struct nsID__bindgen_vtable(::std::os::raw::c_void); #[repr(C)] #[derive(Debug, Copy)] pub struct nsID { diff --git a/tests/expectations/tests/virtual_dtor.rs b/tests/expectations/tests/virtual_dtor.rs index 0c410977..e5d3ace2 100644 --- a/tests/expectations/tests/virtual_dtor.rs +++ b/tests/expectations/tests/virtual_dtor.rs @@ -5,9 +5,7 @@ #[repr(C)] -#[derive(Default)] -pub struct nsSlots__bindgen_vtable { -} +pub struct nsSlots__bindgen_vtable(::std::os::raw::c_void); #[repr(C)] #[derive(Debug)] pub struct nsSlots { diff --git a/tests/expectations/tests/virtual_inheritance.rs b/tests/expectations/tests/virtual_inheritance.rs index 6896eb31..b3119ca7 100644 --- a/tests/expectations/tests/virtual_inheritance.rs +++ b/tests/expectations/tests/virtual_inheritance.rs @@ -25,9 +25,7 @@ impl Clone for A { fn clone(&self) -> Self { *self } } #[repr(C)] -#[derive(Default)] -pub struct B__bindgen_vtable { -} +pub struct B__bindgen_vtable(::std::os::raw::c_void); #[repr(C)] #[derive(Debug, Copy)] pub struct B { @@ -53,9 +51,7 @@ impl Default for B { fn default() -> Self { unsafe { ::std::mem::zeroed() } } } #[repr(C)] -#[derive(Default)] -pub struct C__bindgen_vtable { -} +pub struct C__bindgen_vtable(::std::os::raw::c_void); #[repr(C)] #[derive(Debug, Copy)] pub struct C { diff --git a/tests/expectations/tests/virtual_overloaded.rs b/tests/expectations/tests/virtual_overloaded.rs index e7ae9f4a..625abe3b 100644 --- a/tests/expectations/tests/virtual_overloaded.rs +++ b/tests/expectations/tests/virtual_overloaded.rs @@ -5,9 +5,7 @@ #[repr(C)] -#[derive(Default)] -pub struct C__bindgen_vtable { -} +pub struct C__bindgen_vtable(::std::os::raw::c_void); #[repr(C)] #[derive(Debug, Copy)] pub struct C { diff --git a/tests/expectations/tests/vtable_recursive_sig.rs b/tests/expectations/tests/vtable_recursive_sig.rs index 716ce39f..0faf37ac 100644 --- a/tests/expectations/tests/vtable_recursive_sig.rs +++ b/tests/expectations/tests/vtable_recursive_sig.rs @@ -23,9 +23,7 @@ impl Default for Derived { fn default() -> Self { unsafe { ::std::mem::zeroed() } } } #[repr(C)] -#[derive(Default)] -pub struct Base__bindgen_vtable { -} +pub struct Base__bindgen_vtable(::std::os::raw::c_void); #[repr(C)] #[derive(Debug, Copy)] pub struct Base { diff --git a/tests/headers/generate-inline.hpp b/tests/headers/generate-inline.hpp new file mode 100644 index 00000000..922ee1ca --- /dev/null +++ b/tests/headers/generate-inline.hpp @@ -0,0 +1,12 @@ +// bindgen-flags: --generate-inline-functions + +class Foo { + public: + static inline int bar() { + return 42; + } +}; + +inline int foo() { + return 42; +} diff --git a/tests/tests.rs b/tests/tests.rs index 6b69e0d4..84b5e076 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -3,7 +3,7 @@ extern crate diff; extern crate bindgen; extern crate shlex; -use bindgen::Builder; +use bindgen::{Builder, builder}; use std::fs; use std::io::{BufRead, BufReader, Error, ErrorKind, Read, Write}; use std::path::PathBuf; @@ -144,3 +144,19 @@ macro_rules! test_header { // This file is generated by build.rs include!(concat!(env!("OUT_DIR"), "/tests.rs")); + +#[test] +fn test_header_contents() { + let bindings = builder() + .header_contents("test.h", "int foo(const char* a);") + .no_unstable_rust() + .generate() + .unwrap() + .to_string(); + assert_eq!(bindings, "/* automatically generated by rust-bindgen */ + +extern \"C\" { + pub fn foo(a: *const ::std::os::raw::c_schar) -> ::std::os::raw::c_int; +} +"); +} |