Skip to content

Discovery callbacks for functions and methods. #3140

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,8 @@ enum NamedEnum {
Fish,
};

typedef enum NamedEnum AliasOfNamedEnum;
typedef enum NamedEnum AliasOfNamedEnum;

// Functions

void named_function();
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Methods

class SomeClass {
public:
void named_method();
};
110 changes: 103 additions & 7 deletions bindgen-tests/tests/parse_callbacks/item_discovery_callback/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,28 @@ impl ParseCallbacks for ItemDiscovery {
self.0.borrow_mut().insert(_id, _item);
}
}
#[test]
pub fn test_item_discovery_callback() {

fn test_item_discovery_callback(
header: &str,
expected: HashMap<DiscoveredItemId, DiscoveredItem>,
) {
let discovery = ItemDiscovery::default();
let info = Rc::clone(&discovery.0);

let mut header_path = env!("CARGO_MANIFEST_DIR").to_string();
header_path.push_str(header);

Builder::default()
.header(concat!(
env!("CARGO_MANIFEST_DIR"),
"/tests/parse_callbacks/item_discovery_callback/header_item_discovery.h"
))
.header(header_path)
.parse_callbacks(Box::new(discovery))
.generate()
.expect("TODO: panic message");

compare_item_caches(&info.borrow(), &expected);
}

#[test]
fn test_item_discovery_callback_c() {
let expected = ItemCache::from([
(
DiscoveredItemId::new(10),
Expand Down Expand Up @@ -87,9 +95,37 @@ pub fn test_item_discovery_callback() {
final_name: "_bindgen_ty_*".to_string(),
},
),
(
DiscoveredItemId::new(41),
DiscoveredItem::Function {
final_name: "named_function".to_string(),
},
),
]);
test_item_discovery_callback(
"/tests/parse_callbacks/item_discovery_callback/header_item_discovery.h", expected);
}

compare_item_caches(&info.borrow(), &expected);
#[test]
fn test_item_discovery_callback_cpp() {
let expected = ItemCache::from([
(
DiscoveredItemId::new(1),
DiscoveredItem::Struct {
original_name: Some("SomeClass".to_string()),
final_name: "SomeClass".to_string(),
},
),
(
DiscoveredItemId::new(2),
DiscoveredItem::Method {
final_name: "named_method".to_string(),
parent: DiscoveredItemId::new(1),
},
),
]);
test_item_discovery_callback(
"/tests/parse_callbacks/item_discovery_callback/header_item_discovery.hpp", expected);
}

pub fn compare_item_caches(generated: &ItemCache, expected: &ItemCache) {
Expand Down Expand Up @@ -142,6 +178,12 @@ fn compare_item_info(
DiscoveredItem::Enum { .. } => {
compare_enum_info(expected_item, generated_item)
}
DiscoveredItem::Function { .. } => {
compare_function_info(expected_item, generated_item)
}
DiscoveredItem::Method { .. } => {
compare_method_info(expected_item, generated_item)
}
}
}

Expand Down Expand Up @@ -279,3 +321,57 @@ pub fn compare_alias_info(

compare_item_info(expected_aliased, generated_aliased, expected, generated)
}

pub fn compare_function_info(
expected_item: &DiscoveredItem,
generated_item: &DiscoveredItem,
) -> bool {
let DiscoveredItem::Function {
final_name: expected_final_name,
} = expected_item
else {
unreachable!()
};

let DiscoveredItem::Function {
final_name: generated_final_name,
} = generated_item
else {
unreachable!()
};

if !compare_names(expected_final_name, generated_final_name) {
return false;
}
true
}

pub fn compare_method_info(
expected_item: &DiscoveredItem,
generated_item: &DiscoveredItem,
) -> bool {
let DiscoveredItem::Method {
final_name: expected_final_name,
parent: expected_parent,
} = expected_item
else {
unreachable!()
};

let DiscoveredItem::Method {
final_name: generated_final_name,
parent: generated_parent,
} = generated_item
else {
unreachable!()
};

if expected_parent != generated_parent {
return false;
}

if !compare_names(expected_final_name, generated_final_name) {
return false;
}
true
}
16 changes: 15 additions & 1 deletion bindgen/callbacks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,21 @@ pub enum DiscoveredItem {
/// The final name of the generated binding
final_name: String,
},
// functions, modules, etc.

/// A function or method.
Function {
/// The final name used.
final_name: String,
},

/// A method.
Method {
/// The final name used.
final_name: String,

/// Type to which this method belongs.
parent: DiscoveredItemId,
}, // modules, etc.
}

/// Relevant information about a type to which new derive attributes will be added using
Expand Down
30 changes: 26 additions & 4 deletions bindgen/codegen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2481,6 +2481,7 @@ impl CodeGenerator for CompInfo {

let is_rust_union = is_union && struct_layout.is_rust_union();

let discovered_id = DiscoveredItemId::new(item.id().as_usize());
ctx.options().for_each_callback(|cb| {
let discovered_item = match self.kind() {
CompKind::Struct => DiscoveredItem::Struct {
Expand All @@ -2501,10 +2502,7 @@ impl CodeGenerator for CompInfo {
},
};

cb.new_item_found(
DiscoveredItemId::new(item.id().as_usize()),
discovered_item,
);
cb.new_item_found(discovered_id, discovered_item);
});

// The custom derives callback may return a list of derive attributes;
Expand Down Expand Up @@ -2711,6 +2709,7 @@ impl CodeGenerator for CompInfo {
&mut method_names,
result,
self,
discovered_id,
);
}
}
Expand All @@ -2729,6 +2728,7 @@ impl CodeGenerator for CompInfo {
&mut method_names,
result,
self,
discovered_id,
);
}
}
Expand All @@ -2742,6 +2742,7 @@ impl CodeGenerator for CompInfo {
&mut method_names,
result,
self,
discovered_id,
);
}
}
Expand Down Expand Up @@ -2999,6 +3000,7 @@ impl Method {
method_names: &mut HashSet<String>,
result: &mut CodegenResult<'_>,
_parent: &CompInfo,
parent_id: DiscoveredItemId,
) {
assert!({
let cc = &ctx.options().codegen_config;
Expand All @@ -3019,6 +3021,7 @@ impl Method {

// First of all, output the actual function.
let function_item = ctx.resolve_item(self.signature());
let id = DiscoveredItemId::new(function_item.id().as_usize());
if !function_item.process_before_codegen(ctx, result) {
return;
}
Expand Down Expand Up @@ -3065,6 +3068,16 @@ impl Method {

method_names.insert(name.clone());

ctx.options().for_each_callback(|cb| {
cb.new_item_found(
id,
DiscoveredItem::Method {
parent: parent_id,
final_name: name.clone(),
},
)
});

let mut function_name = function_item.canonical_name(ctx);
if times_seen > 0 {
write!(&mut function_name, "{times_seen}").unwrap();
Expand Down Expand Up @@ -4540,6 +4553,7 @@ impl CodeGenerator for Function {
) -> Self::Return {
debug!("<Function as CodeGenerator>::codegen: item = {item:?}");
debug_assert!(item.is_enabled_for_codegen(ctx));
let id = DiscoveredItemId::new(item.id().as_usize());

let is_internal = matches!(self.linkage(), Linkage::Internal);

Expand Down Expand Up @@ -4650,6 +4664,14 @@ impl CodeGenerator for Function {
if times_seen > 0 {
write!(&mut canonical_name, "{times_seen}").unwrap();
}
ctx.options().for_each_callback(|cb| {
cb.new_item_found(
id,
DiscoveredItem::Function {
final_name: canonical_name.to_string(),
},
);
});

let link_name_attr = self.link_name().or_else(|| {
let mangled_name = mangled_name.unwrap_or(name);
Expand Down
Loading