diff --git a/src/callbacks.rs b/src/callbacks.rs index 9b34544947..d0eb466734 100644 --- a/src/callbacks.rs +++ b/src/callbacks.rs @@ -31,6 +31,12 @@ pub trait ParseCallbacks: fmt::Debug + UnwindSafe { MacroParsingBehavior::Default } + /// This function will run for every function. The returned value determines the name visible + /// in the bindings. + fn generated_name_override(&self, _function_name: &str) -> Option { + None + } + /// The integer kind an integer macro should have, given a name and the /// value of that macro, or `None` if you want the default to be chosen. fn int_macro(&self, _name: &str, _value: i64) -> Option { diff --git a/src/ir/function.rs b/src/ir/function.rs index e8e2c2dfed..288c049bf0 100644 --- a/src/ir/function.rs +++ b/src/ir/function.rs @@ -635,6 +635,12 @@ impl ClangSubItemParser for Function { // but seems easy enough to handle it here. name.push_str("_destructor"); } + if let Some(callbacks) = context.parse_callbacks() { + if let Some(nm) = callbacks.generated_name_override(&name) { + name = nm; + } + } + assert!(!name.is_empty(), "Empty function name."); let mangled_name = cursor_mangling(context, &cursor); let comment = cursor.raw_comment(); diff --git a/tests/expectations/tests/issue-1375-prefixed-functions.rs b/tests/expectations/tests/issue-1375-prefixed-functions.rs new file mode 100644 index 0000000000..835b75790d --- /dev/null +++ b/tests/expectations/tests/issue-1375-prefixed-functions.rs @@ -0,0 +1,11 @@ +#![allow( + dead_code, + non_snake_case, + non_camel_case_types, + non_upper_case_globals +)] + +extern "C" { + #[link_name = "\u{1}my_custom_prefix_function_name"] + pub fn function_name(x: ::std::os::raw::c_int); +} diff --git a/tests/headers/issue-1375-prefixed-functions.h b/tests/headers/issue-1375-prefixed-functions.h new file mode 100644 index 0000000000..4264e52d65 --- /dev/null +++ b/tests/headers/issue-1375-prefixed-functions.h @@ -0,0 +1,4 @@ +// bindgen-parse-callbacks: remove-function-prefix-my_custom_prefix_ + +void my_custom_prefix_function_name(const int x); + diff --git a/tests/parse_callbacks/mod.rs b/tests/parse_callbacks/mod.rs index b94b54de0b..2dc35a6d2c 100644 --- a/tests/parse_callbacks/mod.rs +++ b/tests/parse_callbacks/mod.rs @@ -1,5 +1,29 @@ use bindgen::callbacks::*; +#[derive(Debug)] +pub struct RemoveFunctionPrefixParseCallback { + pub remove_function_prefix: Option, +} + +impl RemoveFunctionPrefixParseCallback { + pub fn new(prefix: &str) -> Self { + RemoveFunctionPrefixParseCallback { + remove_function_prefix: Some(prefix.to_string()), + } + } +} + +impl ParseCallbacks for RemoveFunctionPrefixParseCallback { + fn generated_name_override(&self, function_name: &str) -> Option { + if let Some(prefix) = &self.remove_function_prefix { + if function_name.starts_with(prefix) { + return Some(function_name[prefix.len()..].to_string()); + } + } + None + } +} + #[derive(Debug)] struct EnumVariantRename; @@ -37,6 +61,18 @@ pub fn lookup(cb: &str) -> Box { "blocklisted-type-implements-trait" => { Box::new(BlocklistedTypeImplementsTrait) } - _ => panic!("Couldn't find name ParseCallbacks: {}", cb), + call_back => { + if call_back.starts_with("remove-function-prefix-") { + let prefix = call_back + .split("remove-function-prefix-") + .last() + .to_owned(); + let lnopc = + RemoveFunctionPrefixParseCallback::new(prefix.unwrap()); + Box::new(lnopc) + } else { + panic!("Couldn't find name ParseCallbacks: {}", cb) + } + } } }