summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore5
-rw-r--r--src/bin/bindgen.rs6
-rw-r--r--src/clang.rs8
-rw-r--r--src/gen.rs13
-rw-r--r--src/lib.rs4
-rw-r--r--src/parser.rs29
6 files changed, 48 insertions, 17 deletions
diff --git a/.gitignore b/.gitignore
index bcc3a4e0..f54aca98 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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 {
diff --git a/src/gen.rs b/src/gen.rs
index 4d296386..e046ea12 100644
--- a/src/gen.rs
+++ b/src/gen.rs
@@ -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()
}]
}),
diff --git a/src/lib.rs b/src/lib.rs
index 3ffc929e..db8c8348 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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();