Skip to content

Commit 587e166

Browse files
committed
Fix handling boxed classes returned by reference
1 parent acd1922 commit 587e166

File tree

5 files changed

+48
-16
lines changed

5 files changed

+48
-16
lines changed

binding-generator/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// todo support converting pointer + size to slice of Mat and other similar objects
22
// todo add support for arrays in dnn::DictValue
33
// todo allow ergonomically combining of enum variants with |
4-
// todo cv_utils_logging_internal_getGlobalLogTag() returns LogTag**, but Rust interprets it as LogTag*, check why it doesn't crash and fix if needed
54
// todo almost everything from the manual module must be connected to the binding generator, not the main crate
65
// todo check that FN_FaceDetector works at all (receiving InputArray, passing as callback)
76
// fixme vector<Mat*> get's interpreted as Vector<Mat> which should be wrong (e.g. Layer::forward and Layer::apply_halide_scheduler)

binding-generator/src/renderer.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ impl<'a> TypeRefRenderer<'a> for CppExternReturnRenderer {
171171
let type_ref = if kind.as_string(type_ref.type_hint()).is_some() {
172172
Cow::Owned(TypeRef::new_pointer(TypeRefDesc::void()))
173173
} else if kind.extern_pass_kind().is_by_void_ptr() && !kind.as_abstract_class_ptr().is_some() {
174-
Cow::Owned(TypeRef::new_pointer(type_ref.clone()))
174+
Cow::Owned(TypeRef::new_pointer(type_ref.source()))
175175
} else {
176176
Cow::Borrowed(type_ref)
177177
};

binding-generator/src/type_ref.rs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ impl<'tu, 'ge> TypeRef<'tu, 'ge> {
172172
}
173173
}
174174

175-
/// Like canonical(), but also removes indirection by pointer and reference
175+
/// Removes indirection by pointer and reference, this will also remove typedef if it references a pointer or reference
176176
pub fn source(&self) -> Self {
177177
match self.kind().as_ref() {
178178
TypeRefKind::Pointer(inner) | TypeRefKind::Reference(inner) | TypeRefKind::RValueReference(inner) => inner.source(),
@@ -195,8 +195,17 @@ impl<'tu, 'ge> TypeRef<'tu, 'ge> {
195195
TypeRefKind::Pointer(inner) | TypeRefKind::Reference(inner) | TypeRefKind::RValueReference(inner) => {
196196
inner.source_smart()
197197
}
198-
TypeRefKind::Typedef(tdef) => tdef.underlying_type_ref().source_smart(),
199198
TypeRefKind::SmartPtr(ptr) => ptr.pointee().source_smart(),
199+
TypeRefKind::Typedef(tdef) => {
200+
let underlying_type = tdef.underlying_type_ref();
201+
match underlying_type.kind().as_ref() {
202+
TypeRefKind::Pointer(inner) | TypeRefKind::Reference(inner) | TypeRefKind::RValueReference(inner) => {
203+
inner.source_smart()
204+
}
205+
TypeRefKind::SmartPtr(ptr) => ptr.pointee().source_smart(),
206+
_ => self.clone(),
207+
}
208+
}
200209
_ => self.clone(),
201210
}
202211
}
@@ -205,10 +214,19 @@ impl<'tu, 'ge> TypeRef<'tu, 'ge> {
205214
pub fn base(&self) -> Self {
206215
match self.kind().as_ref() {
207216
TypeRefKind::Pointer(inner) | TypeRefKind::Reference(inner) | TypeRefKind::RValueReference(inner) => inner.base(),
208-
TypeRefKind::Typedef(tdef) => tdef.underlying_type_ref().base(),
217+
TypeRefKind::SmartPtr(ptr) => ptr.pointee().base(),
209218
TypeRefKind::Array(inner, ..) => inner.base(),
210219
TypeRefKind::StdVector(vec) => vec.element_type().base(),
211-
TypeRefKind::SmartPtr(ptr) => ptr.pointee().base(),
220+
TypeRefKind::Typedef(tdef) => {
221+
let underlying_type = tdef.underlying_type_ref();
222+
match underlying_type.kind().as_ref() {
223+
TypeRefKind::Pointer(inner) | TypeRefKind::Reference(inner) | TypeRefKind::RValueReference(inner) => inner.base(),
224+
TypeRefKind::SmartPtr(ptr) => ptr.pointee().base(),
225+
TypeRefKind::Array(inner, ..) => inner.base(),
226+
TypeRefKind::StdVector(vec) => vec.element_type().base(),
227+
_ => self.clone(),
228+
}
229+
}
212230
_ => self.clone(),
213231
}
214232
}

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

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -769,15 +769,20 @@ pub fn cpp_return_map<'f>(return_type: &TypeRef, name: &'f str, is_constructor:
769769
};
770770
(str_mk, false)
771771
} else if return_kind.extern_pass_kind().is_by_void_ptr() && !is_constructor {
772-
let out = return_type
773-
.source()
774-
.kind()
775-
.as_class()
776-
.filter(|cls| cls.is_abstract())
777-
.map_or_else(
778-
|| format!("new {typ}({name})", typ = return_type.cpp_name(CppNameStyle::Reference)).into(),
779-
|_| name.into(),
780-
);
772+
let ret_source = return_type.source();
773+
let out = ret_source.kind().as_class().filter(|cls| cls.is_abstract()).map_or_else(
774+
|| {
775+
// todo implement higher count if it's needed
776+
let deref_count = return_type.kind().as_pointer().map_or(0, |_| 1);
777+
format!(
778+
"new {typ}({:*<deref_count$}{name})",
779+
"",
780+
typ = ret_source.cpp_name(CppNameStyle::Reference)
781+
)
782+
.into()
783+
},
784+
|_| name.into(),
785+
);
781786
(out, false)
782787
} else {
783788
(name.into(), return_kind.as_fixed_array().is_some())

tests/marshalling.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Contains all tests that cover marshalling types to and from C++
22
33
use opencv::core;
4-
use opencv::core::{Scalar, Tuple};
4+
use opencv::core::{Scalar, SparseMat, Tuple};
55
use opencv::prelude::*;
66
use opencv::Result;
77

@@ -125,6 +125,16 @@ fn fixed_array_return() -> Result<()> {
125125
Ok(())
126126
}
127127

128+
/// Sometimes functions return a boxed class by pointer, so they need an additional dereference
129+
#[test]
130+
fn boxed_return_by_pointer() -> Result<()> {
131+
let mut sm = SparseMat::from_mat(&Mat::new_rows_cols_with_default(5, 3, i32::opencv_type(), 1.into())?)?;
132+
let hdr = sm.hdr();
133+
assert_eq!(1, hdr.refcount());
134+
assert_eq!(2, hdr.dims());
135+
Ok(())
136+
}
137+
128138
/// Return of an owned String
129139
#[test]
130140
fn string_return() -> Result<()> {

0 commit comments

Comments
 (0)