diff options
author | Emilio Cobos Álvarez <ecoal95@gmail.com> | 2016-03-23 22:45:09 +0100 |
---|---|---|
committer | Emilio Cobos Álvarez <ecoal95@gmail.com> | 2016-03-23 22:45:09 +0100 |
commit | a624bc81095df028859f0982b80881dc6cd38e28 (patch) | |
tree | f6d35e8e5d02a64f38ac9c0d4cdf3c6e718eed68 | |
parent | c5dc73c72530c922bab9128ffbc9f006bf7771ef (diff) |
Allow generating opaque types based on layout
The best example for this is nsPoint et al.
-rw-r--r-- | src/bin/bindgen.rs | 9 | ||||
-rw-r--r-- | src/gen.rs | 35 | ||||
-rw-r--r-- | src/lib.rs | 7 | ||||
-rw-r--r-- | src/types.rs | 13 |
4 files changed, 61 insertions, 3 deletions
diff --git a/src/bin/bindgen.rs b/src/bin/bindgen.rs index 7c52c88d..9919da71 100644 --- a/src/bin/bindgen.rs +++ b/src/bin/bindgen.rs @@ -96,11 +96,18 @@ fn parse_args(args: &[String]) -> ParseResult { } "-blacklist-type" => { if ix + 1 >= args_len { - return ParseResult::ParseErr("Missing blacklist type pattern".to_string()); + return ParseResult::ParseErr("Missing blacklist type name".to_string()); } options.blacklist_type.push(args[ix + 1].clone()); ix += 2; } + "-opaque-type" => { + if ix + 1 >= args_len { + return ParseResult::ParseErr("Missing opaque type name".to_string()); + } + options.opaque_types.push(args[ix + 1].clone()); + ix += 2; + } "-builtins" => { options.builtins = true; ix += 1; @@ -399,10 +399,18 @@ fn gen_mod(mut ctx: &mut GenCtx, } } +fn type_opaque(ctx: &GenCtx, global: &Global) -> bool { + let global_name = global.name(); + + // Can't make an opaque type without layout + global.layout().is_some() && + ctx.options.opaque_types.iter().any(|name| *name == global_name) +} + fn type_blacklisted(ctx: &GenCtx, global: &Global) -> bool { let global_name = global.name(); - ctx.options.blacklist_type.iter().all(|name| *name != global_name) + ctx.options.blacklist_type.iter().any(|name| *name == global_name) } fn gen_globals(mut ctx: &mut GenCtx, @@ -441,7 +449,16 @@ fn gen_globals(mut ctx: &mut GenCtx, gs = remove_redundant_decl(gs); for g in gs.into_iter() { - if !type_blacklisted(ctx, &g) { + if type_blacklisted(ctx, &g) { + continue; + } + + if type_opaque(ctx, &g) { + let name = first(rust_id(ctx, &g.name())); + let layout = g.layout().unwrap(); + defs.push(mk_opaque_struct(ctx, &name, &layout)); + // This should always be true but anyways.. + defs.push(mk_test_fn(ctx, &name, &layout)); continue; } @@ -2133,3 +2150,17 @@ fn mk_test_fn(ctx: &GenCtx, name: &str, layout: &Layout) -> P<ast::Item> { }).unwrap(); item } + +fn mk_opaque_struct(ctx: &GenCtx, name: &str, layout: &Layout) -> P<ast::Item> { + let size = layout.size; + let struct_name = ctx.ext_cx.ident_of(name); + + let item = quote_item!(&ctx.ext_cx, + #[repr(C)] + #[derive(Copy, Clone, Debug)] + struct $struct_name { + _bindgen_opaque_blob: [u8; $size] + } + ).unwrap(); + item +} @@ -56,6 +56,11 @@ impl<'a> Builder<'a> { self } + pub fn opaque_type<T: Into<String>>(&mut self, arg: T) -> &mut Self { + self.options.opaque_types.push(arg.into()); + self + } + pub fn clang_arg<T: Into<String>>(&mut self, arg: T) -> &mut Self { self.options.clang_args.push(arg.into()); self @@ -120,6 +125,7 @@ impl<'a> Default for Builder<'a> { pub struct BindgenOptions { pub match_pat: Vec<String>, pub blacklist_type: Vec<String>, + pub opaque_types: Vec<String>, pub builtins: bool, pub rust_enums: bool, pub links: Vec<(String, LinkType)>, @@ -138,6 +144,7 @@ impl Default for BindgenOptions { BindgenOptions { match_pat: Vec::new(), blacklist_type: Vec::new(), + opaque_types: Vec::new(), builtins: false, rust_enums: true, links: Vec::new(), diff --git a/src/types.rs b/src/types.rs index 166457ec..792965c2 100644 --- a/src/types.rs +++ b/src/types.rs @@ -77,6 +77,19 @@ impl Global { } } + pub fn layout(&self) -> Option<Layout> { + Some(match *self { + GType(ref info) => info.borrow().layout, + GComp(ref info) + | GCompDecl(ref info) => info.borrow().layout, + GEnum(ref info) + | GEnumDecl(ref info) => info.borrow().layout, + GVar(_) + | GFunc(_) + | GOther => return None, + }) + } + pub fn compinfo(&self) -> Rc<RefCell<CompInfo>> { match *self { GComp(ref i) |