diff options
-rw-r--r-- | .gitignore | 5 | ||||
-rw-r--r-- | src/bin/bindgen.rs | 6 | ||||
-rw-r--r-- | src/clang.rs | 8 | ||||
-rw-r--r-- | src/gen.rs | 13 | ||||
-rw-r--r-- | src/lib.rs | 4 | ||||
-rw-r--r-- | src/parser.rs | 29 |
6 files changed, 48 insertions, 17 deletions
@@ -3,4 +3,7 @@ libbindgen* # Cargo target/ -Cargo.lock
\ No newline at end of file +Cargo.lock +*~ +#*# + diff --git a/src/bin/bindgen.rs b/src/bin/bindgen.rs index 7ad4d07f..443a0ff0 100644 --- a/src/bin/bindgen.rs +++ b/src/bin/bindgen.rs @@ -166,6 +166,10 @@ fn parse_args(args: &[String]) -> ParseResult { options.raw_lines.push(args[ix + 1].clone()); ix += 2; } + "-use-msvc-mangling" => { + options.msvc_mangling = true; + ix += 1; + } _ => { options.clang_args.push(args[ix].clone()); ix += 1; @@ -201,6 +205,8 @@ Options: -allow-unknown-types Don't fail if we encounter types we do not support, instead treat them as void -emit-clang-ast Output the ast (for debugging purposes) + -use-msvc-mangling Handle MSVC C++ ABI mangling; requires that --target + be set to (i686|x86_64)-pc-win32 -override-enum-type <type> Override enum type, type name could be uchar schar diff --git a/src/clang.rs b/src/clang.rs index 2f6e6223..c230460d 100644 --- a/src/clang.rs +++ b/src/clang.rs @@ -32,15 +32,9 @@ impl Cursor { } pub fn mangling(&self) -> String { - let mut mangling = unsafe { + unsafe { String_ { x: clang_Cursor_getMangling(self.x) }.to_string() - }; - - // Try to undo backend mangling - if cfg!(target_os = "macos") || cfg!(all(target_os = "windows", target_env = "gnu")) { - mangling.remove(0); } - mangling } pub fn lexical_parent(&self) -> Cursor { @@ -70,8 +70,16 @@ fn ref_eq<T>(thing: &T, other: &T) -> bool { fn rust_id(ctx: &mut GenCtx, name: &str) -> (String, bool) { let token = parse::token::Ident(ctx.ext_cx.ident_of(name)); - if token.is_any_keyword() || "bool" == name { + if token.is_any_keyword() || + name.contains("@") || + name.contains("?") || + name.contains("$") || + "bool" == name + { let mut s = name.to_owned(); + s = s.replace("@", "_"); + s = s.replace("?", "_"); + s = s.replace("$", "_"); s.push_str("_"); (s, true) } else { @@ -214,6 +222,7 @@ fn gen_unmangle_method(ctx: &mut GenCtx, constness: ast::Constness::NotConst, }; + let mangled_rs = first(rust_id(ctx, &v.mangled)); let call = P(ast::Expr { id: ast::DUMMY_NODE_ID, node: ast::ExprKind::Call( @@ -223,7 +232,7 @@ fn gen_unmangle_method(ctx: &mut GenCtx, span: ctx.span, global: false, segments: vec![ast::PathSegment { - identifier: ctx.ext_cx.ident_of(&v.mangled), + identifier: ctx.ext_cx.ident_of(&mangled_rs), parameters: ast::PathParameters::none() }] }), @@ -170,6 +170,8 @@ pub struct BindgenOptions { pub class_constants: bool, /// Wether to generate names that are **directly** under namespaces. pub namespaced_constants: bool, + // whether to use msvc mangling rules + pub msvc_mangling: bool, pub override_enum_ty: String, pub raw_lines: Vec<String>, /// Attributes for a type with destructor @@ -197,6 +199,7 @@ impl Default for BindgenOptions { unstable_rust: true, class_constants: true, namespaced_constants: true, + msvc_mangling: false, raw_lines: vec![], dtor_attrs: vec![], clang_args: vec![], @@ -325,6 +328,7 @@ fn parse_headers(options: &BindgenOptions, logger: &Logger) -> Result<ModuleMap, clang_args: options.clang_args.clone(), opaque_types: options.opaque_types.clone(), blacklist_type: options.blacklist_type.clone(), + msvc_mangling: options.msvc_mangling, }; parser::parse(clang_opts, logger) diff --git a/src/parser.rs b/src/parser.rs index 71a6dff9..de1242be 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -31,6 +31,7 @@ pub struct ClangParserOptions { pub clang_args: Vec<String>, pub opaque_types: Vec<String>, pub blacklist_type: Vec<String>, + pub msvc_mangling: bool, } struct ClangParserCtx<'a> { @@ -66,6 +67,18 @@ impl<'a> ClangParserCtx<'a> { } } +fn cursor_link_name(ctx: &mut ClangParserCtx, cursor: &Cursor) -> String { + let mut mangling = cursor.mangling(); + + // Try to undo backend linkage munging (prepended _, generally) + if cfg!(target_os = "macos") || + (cfg!(target_os = "windows") && !ctx.options.msvc_mangling) + { + mangling.remove(0); + } + mangling +} + fn match_pattern(ctx: &mut ClangParserCtx, cursor: &Cursor) -> bool { let (file, _, _, _) = cursor.location().location(); @@ -195,7 +208,7 @@ fn decl_name(ctx: &mut ClangParserCtx, cursor: &Cursor) -> Global { GType(ti) } CXCursor_VarDecl => { - let mangled = cursor.mangling(); + let mangled = cursor_link_name(ctx, &cursor); let is_const = ty.is_const(); let ty = conv_ty_resolving_typedefs(ctx, &ty, &cursor, true); let mut vi = VarInfo::new(spelling, mangled, comment, ty); @@ -211,7 +224,7 @@ fn decl_name(ctx: &mut ClangParserCtx, cursor: &Cursor) -> Global { GVar(vi) } CXCursor_FunctionDecl => { - let mangled = cursor.mangling(); + let mangled = cursor_link_name(ctx, &cursor); let vi = Rc::new(RefCell::new(VarInfo::new(spelling, mangled, comment, TVoid))); GFunc(vi) } @@ -890,6 +903,12 @@ fn visit_composite(cursor: &Cursor, parent: &Cursor, ci.base_members += 1; } CXCursor_CXXMethod => { + // Make sure to mark has_vtable properly, even if we + // would otherwise skip this method due to linkage/visibility. + if cursor.method_is_virtual() { + ci.has_vtable = true; + } + let linkage = cursor.linkage(); if linkage != CXLinkage_External { return CXChildVisit_Continue; @@ -942,10 +961,6 @@ fn visit_composite(cursor: &Cursor, parent: &Cursor, return false; } - if cursor.method_is_virtual() { - ci.has_vtable = true; - } - let mut sig = mk_fn_sig_resolving_typedefs(ctx, &cursor.cur_type(), cursor, &ci.typedefs); if !cursor.method_is_static() { // XXX what have i done @@ -971,7 +986,7 @@ fn visit_composite(cursor: &Cursor, parent: &Cursor, return CXChildVisit_Continue; } - let mut vi = VarInfo::new(spelling, cursor.mangling(), cursor.raw_comment(), sig); + let mut vi = VarInfo::new(spelling, cursor_link_name(ctx, &cursor), cursor.raw_comment(), sig); vi.is_static = cursor.method_is_static(); vi.is_const = cursor.cur_type().is_const(); |