Skip to content

Commit 0eb0e92

Browse files
committed
Fix linking issue when video module is used without tracking
1 parent fc0a2ef commit 0eb0e92

File tree

4 files changed

+46
-16
lines changed

4 files changed

+46
-16
lines changed

binding-generator/src/entity.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ pub trait EntityExt<'tu> {
7777
fn walk_fields_while(&self, predicate: impl FnMut(Entity<'tu>) -> ControlFlow<()>) -> ControlFlow<()>;
7878
fn walk_consts_while(&self, predicate: impl FnMut(Entity<'tu>) -> ControlFlow<()>) -> ControlFlow<()>;
7979
fn walk_methods_while(&self, predicate: impl FnMut(Entity<'tu>) -> ControlFlow<()>) -> ControlFlow<()>;
80+
fn walk_parents<T>(&self, predicate: impl FnMut(Entity<'tu>) -> ControlFlow<T>) -> ControlFlow<T>;
8081
}
8182

8283
impl<'tu> EntityExt<'tu> for Entity<'tu> {
@@ -149,6 +150,17 @@ impl<'tu> EntityExt<'tu> for Entity<'tu> {
149150
_ => ControlFlow::Continue(()),
150151
})
151152
}
153+
154+
fn walk_parents<T>(&self, mut predicate: impl FnMut(Entity<'tu>) -> ControlFlow<T>) -> ControlFlow<T> {
155+
let mut current = *self;
156+
while let Some(parent) = current.get_semantic_parent() {
157+
match predicate(parent) {
158+
ControlFlow::Continue(()) => current = parent,
159+
ControlFlow::Break(out) => return ControlFlow::Break(out),
160+
}
161+
}
162+
ControlFlow::Continue(())
163+
}
152164
}
153165

154166
#[allow(unused)]

binding-generator/src/writer/rust_native/element.rs

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
use std::borrow::Cow;
22
use std::fmt::Debug;
3+
use std::ops::ControlFlow;
34

45
use clang::{Entity, EntityKind};
56

67
use super::comment::RenderComment;
78
use crate::type_ref::FishStyle;
89
use crate::{
9-
opencv_module_from_path, reserved_rename, settings, CppNameStyle, Element, GeneratedType, IteratorExt, NameStyle, StringExt,
10-
SupportedModule,
10+
opencv_module_from_path, reserved_rename, settings, CppNameStyle, Element, EntityExt, GeneratedType, IteratorExt, NameStyle,
11+
StringExt, SupportedModule,
1112
};
1213

1314
pub struct DefaultRustNativeElement;
@@ -20,7 +21,7 @@ impl DefaultRustNativeElement {
2021
.get_spelling_location()
2122
.file
2223
.and_then(|file| opencv_module_from_path(&file.get_path()))
23-
.unwrap_or(SupportedModule::Core)
24+
.map_or(SupportedModule::Core, |m| rust_module_hack(entity, m))
2425
}
2526

2627
pub fn rust_module_reference(this: &(impl RustElement + ?Sized)) -> Cow<'_, str> {
@@ -148,3 +149,28 @@ impl<'ne, 'tu: 'ne, 'ge: 'ne> AsRef<dyn RustNativeGeneratedElement + 'ne> for Ge
148149
}
149150
}
150151
}
152+
153+
/// Adjusts the module for certain entities that are technically in one module but actually implemented in another.
154+
///
155+
/// One (and for now the only) example is that some class declarations are technically in `hpp` files in the `video` module, but
156+
/// their code is actually in the `tracking` module of `opencv_contrib`. This mismatch leads to linking errors if only the
157+
/// `opencv_video` module is linked.
158+
fn rust_module_hack(entity: Entity, module_from_path: SupportedModule) -> SupportedModule {
159+
match module_from_path {
160+
SupportedModule::Video => {
161+
let break_res = entity.walk_parents(|parent| match parent.get_kind() {
162+
EntityKind::Namespace if parent.is_inline_namespace() && parent.get_name().is_some_and(|n| n == "tracking") => {
163+
ControlFlow::Break(SupportedModule::Tracking)
164+
}
165+
_ => ControlFlow::Continue(()),
166+
});
167+
// todo: MSRV 1.83 use `break_value()`
168+
match break_res {
169+
ControlFlow::Break(m) => Some(m),
170+
ControlFlow::Continue(_) => None,
171+
}
172+
.unwrap_or(module_from_path)
173+
}
174+
_ => module_from_path,
175+
}
176+
}

binding-generator/src/writer/rust_native/mod.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,11 @@ impl<'s> RustNativeBindingWriter<'s> {
117117

118118
impl GeneratorVisitor<'_> for RustNativeBindingWriter<'_> {
119119
fn wants_file(&mut self, path: &Path) -> bool {
120-
opencv_module_from_path(path) == Some(self.module)
120+
match self.module {
121+
// tracking_legacy.hpp includes header from the video module, but we need those definitions in the tracking module
122+
SupportedModule::Tracking if path.ends_with("video/detail/tracking.detail.hpp") => true,
123+
_ => opencv_module_from_path(path) == Some(self.module),
124+
}
121125
}
122126

123127
fn visit_module_comment(&mut self, comment: String) {

src_cpp/video.hpp

Lines changed: 0 additions & 12 deletions
This file was deleted.

0 commit comments

Comments
 (0)