summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmilio Cobos Álvarez <ecoal95@gmail.com>2016-03-23 22:45:09 +0100
committerEmilio Cobos Álvarez <ecoal95@gmail.com>2016-03-23 22:45:09 +0100
commita624bc81095df028859f0982b80881dc6cd38e28 (patch)
treef6d35e8e5d02a64f38ac9c0d4cdf3c6e718eed68
parentc5dc73c72530c922bab9128ffbc9f006bf7771ef (diff)
Allow generating opaque types based on layout
The best example for this is nsPoint et al.
-rw-r--r--src/bin/bindgen.rs9
-rw-r--r--src/gen.rs35
-rw-r--r--src/lib.rs7
-rw-r--r--src/types.rs13
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;
diff --git a/src/gen.rs b/src/gen.rs
index d4bd277c..a69ee861 100644
--- a/src/gen.rs
+++ b/src/gen.rs
@@ -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
+}
diff --git a/src/lib.rs b/src/lib.rs
index 998ca7e5..32f8cec0 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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)