Enable tracking module
Also improve Mat_ usability
MODIFY
binding-generator/src/class.rs
binding-generator/src/class.rs
@@ -558,8 +558,12 @@ impl Element for Class<'_, '_> {
}
fn rust_leafname(&self) -> Cow<str> {
+ if self.type_ref().is_string() {
+ "String".into()
+ } else {
self.cpp_localname()
}
+ }
fn rust_localname(&self) -> Cow<str> {
DefaultElement::rust_localname(self)

MODIFY
binding-generator/src/func.rs
binding-generator/src/func.rs
@@ -606,7 +606,7 @@ impl<'tu, 'g> Func<'tu, 'g> {
let is_safe = !settings::FUNC_UNSAFE.contains(identifier.as_ref());
let return_type = self.return_type();
let return_type_func_decl = if is_infallible {
- return_type.rust_return_func_decl()
+ return_type.rust_return_func_decl(false)
} else {
return_type.rust_return_func_decl_wrapper()
};

MODIFY
binding-generator/src/function.rs
binding-generator/src/function.rs
@@ -87,7 +87,7 @@ impl Element for Function<'_, '_> {
fn cpp_localname(&self) -> Cow<str> {
let args = self.arguments().into_iter()
- .map(|a| a.type_ref().cpp_full().into_owned())
+ .map(|a| a.type_ref().cpp_full_native("").into_owned())
.join(", ");
let ret = self.return_type();
format!("{ret} (*)({args})", args=args, ret=ret.cpp_full()).into()

MODIFY
binding-generator/src/settings.rs
binding-generator/src/settings.rs
@@ -341,7 +341,6 @@ pub static FUNC_RENAME: Lazy<HashMap<&str, &str>> = Lazy::new(|| hashmap! {
"cv_dnn_Layer_finalize_const_vector_MatX_X_vector_Mat_X" => "-", // dup of cv_dnn_Layer_finalize_const_vector_Mat_X_vector_Mat_X
// ### face ###
- "cv_face_FacemarkKazemi_setFaceDetector_bool__X__const_cv__InputArrayX__const_cv__OutputArrayX__voidX__voidX" => "-", // fixme
"cv_face_FacemarkLBF_Params_pupils" => "-", // fixme array of vectors
// ### features2d ###
@@ -472,41 +471,49 @@ pub static FUNC_RENAME: Lazy<HashMap<&str, &str>> = Lazy::new(|| hashmap! {
pub static FUNC_CFG_ATTR: Lazy<HashMap<&str, (&str, &str)>> = Lazy::new(|| hashmap! {
// ### core ###
- "cv_MatConstIterator_MatConstIterator_const_MatX_const_intX" => (
- "not(target_os = \"windows\")", "!defined(OCVRS_TARGET_OS_WINDOWS)"
- ), // missing in windows dll
- "cv_SparseMatIterator_SparseMatIterator_SparseMatX_const_intX" => (
- "not(target_os = \"windows\")", "!defined(OCVRS_TARGET_OS_WINDOWS)"
- ), // missing in windows dll
- "cv_getImpl_vector_int_X_vector_String_X" => (
- "not(target_os = \"windows\")", "!defined(OCVRS_TARGET_OS_WINDOWS)"
- ), // missing in windows dll
+ "cv_MatConstIterator_MatConstIterator_const_MatX_const_intX" => ("not(target_os = \"windows\")", "!defined(OCVRS_TARGET_OS_WINDOWS)"), // missing in windows dll
+ "cv_SparseMatIterator_SparseMatIterator_SparseMatX_const_intX" => ("not(target_os = \"windows\")", "!defined(OCVRS_TARGET_OS_WINDOWS)"), // missing in windows dll
+ "cv_getImpl_vector_int_X_vector_String_X" => ("not(target_os = \"windows\")", "!defined(OCVRS_TARGET_OS_WINDOWS)"), // missing in windows dll
// ### dnn ###
- "cv_dnn_BackendNode_BackendNode_int" => (
- "not(target_os = \"windows\")", "!defined(OCVRS_TARGET_OS_WINDOWS)"
- ), // missing in windows dll
+ "cv_dnn_BackendNode_BackendNode_int" => ("not(target_os = \"windows\")", "!defined(OCVRS_TARGET_OS_WINDOWS)"), // missing in windows dll
// ### imgproc ###
- "cv_getRotationMatrix2D__Point2f_double_double" => (
- "not(target_os = \"windows\")", "!defined(OCVRS_TARGET_OS_WINDOWS)"
- ), // missing in windows dll
+ "cv_getRotationMatrix2D__Point2f_double_double" => ("not(target_os = \"windows\")", "!defined(OCVRS_TARGET_OS_WINDOWS)"), // missing in windows dll
// ### stitching ###
- "cv_createStitcherScans_bool" => (
- "not(target_os = \"windows\")", "!defined(OCVRS_TARGET_OS_WINDOWS)"
- ), // missing in windows dll
- "cv_createStitcher_bool" => (
- "not(target_os = \"windows\")", "!defined(OCVRS_TARGET_OS_WINDOWS)"
- ), // missing in windows dll
+ "cv_createStitcherScans_bool" => ("not(target_os = \"windows\")", "!defined(OCVRS_TARGET_OS_WINDOWS)"), // missing in windows dll
+ "cv_createStitcher_bool" => ("not(target_os = \"windows\")", "!defined(OCVRS_TARGET_OS_WINDOWS)"), // missing in windows dll
// ### surface_matching ###
- "cv_ppf_match_3d_PPF3DDetector_read_const_FileNodeX" => (
- "not(target_os = \"windows\")", "!defined(OCVRS_TARGET_OS_WINDOWS)"
- ), // missing in windows dll
- "cv_ppf_match_3d_PPF3DDetector_write_const_FileStorageX" => (
- "not(target_os = \"windows\")", "!defined(OCVRS_TARGET_OS_WINDOWS)"
- ), // missing in windows dll
+ "cv_ppf_match_3d_PPF3DDetector_read_const_FileNodeX" => ("not(target_os = \"windows\")", "!defined(OCVRS_TARGET_OS_WINDOWS)"), // missing in windows dll
+ "cv_ppf_match_3d_PPF3DDetector_write_const_FileStorageX" => ("not(target_os = \"windows\")", "!defined(OCVRS_TARGET_OS_WINDOWS)"), // missing in windows dll
+
+ // ### tracking ###
+ "cv_CvFeatureParams_CvFeatureParams" => ("not(target_os = \"windows\")", "!defined(OCVRS_TARGET_OS_WINDOWS)"),
+ "cv_CvFeatureParams_create_FeatureType" => ("not(target_os = \"windows\")", "!defined(OCVRS_TARGET_OS_WINDOWS)"),
+ "cv_CvFeatureParams_create_int" => ("not(target_os = \"windows\")", "!defined(OCVRS_TARGET_OS_WINDOWS)"),
+ "cv_CvHaarEvaluator_FeatureHaar_FeatureHaar_Size" => ("not(target_os = \"windows\")", "!defined(OCVRS_TARGET_OS_WINDOWS)"),
+ "cv_CvHaarEvaluator_FeatureHaar_eval_const_const_MatX_Rect_floatX" => ("not(target_os = \"windows\")", "!defined(OCVRS_TARGET_OS_WINDOWS)"),
+ "cv_CvHaarEvaluator_FeatureHaar_getAreas_const" => ("not(target_os = \"windows\")", "!defined(OCVRS_TARGET_OS_WINDOWS)"),
+ "cv_CvHaarEvaluator_FeatureHaar_getInitMean_const" => ("not(target_os = \"windows\")", "!defined(OCVRS_TARGET_OS_WINDOWS)"),
+ "cv_CvHaarEvaluator_FeatureHaar_getInitSigma_const" => ("not(target_os = \"windows\")", "!defined(OCVRS_TARGET_OS_WINDOWS)"),
+ "cv_CvHaarEvaluator_FeatureHaar_getNumAreas" => ("not(target_os = \"windows\")", "!defined(OCVRS_TARGET_OS_WINDOWS)"),
+ "cv_CvHaarEvaluator_FeatureHaar_getWeights_const" => ("not(target_os = \"windows\")", "!defined(OCVRS_TARGET_OS_WINDOWS)"),
+ "cv_CvHaarEvaluator_getFeatures_const" => ("not(target_os = \"windows\")", "!defined(OCVRS_TARGET_OS_WINDOWS)"),
+ "cv_CvHaarEvaluator_setWinSize_Size" => ("not(target_os = \"windows\")", "!defined(OCVRS_TARGET_OS_WINDOWS)"),
+ "cv_CvHaarEvaluator_setWinSize_const" => ("not(target_os = \"windows\")", "!defined(OCVRS_TARGET_OS_WINDOWS)"),
+ "cv_CvHaarEvaluator_writeFeature_const_FileStorageX" => ("not(target_os = \"windows\")", "!defined(OCVRS_TARGET_OS_WINDOWS)"),
+ "cv_TrackerStateEstimatorAdaBoosting_TrackerAdaBoostingTargetState_TrackerAdaBoostingTargetState_const_Point2fX_int_int_bool_const_MatX" => ("not(target_os = \"windows\")", "!defined(OCVRS_TARGET_OS_WINDOWS)"),
+ "cv_TrackerStateEstimatorAdaBoosting_TrackerAdaBoostingTargetState_getTargetResponses_const" => ("not(target_os = \"windows\")", "!defined(OCVRS_TARGET_OS_WINDOWS)"),
+ "cv_TrackerStateEstimatorAdaBoosting_TrackerAdaBoostingTargetState_isTargetFg_const" => ("not(target_os = \"windows\")", "!defined(OCVRS_TARGET_OS_WINDOWS)"),
+ "cv_TrackerStateEstimatorAdaBoosting_TrackerAdaBoostingTargetState_setTargetFg_bool" => ("not(target_os = \"windows\")", "!defined(OCVRS_TARGET_OS_WINDOWS)"),
+ "cv_TrackerStateEstimatorAdaBoosting_TrackerAdaBoostingTargetState_setTargetResponses_const_MatX" => ("not(target_os = \"windows\")", "!defined(OCVRS_TARGET_OS_WINDOWS)"),
+ "cv_TrackerStateEstimatorMILBoosting_TrackerMILTargetState_TrackerMILTargetState_const_Point2fX_int_int_bool_const_MatX" => ("not(target_os = \"windows\")", "!defined(OCVRS_TARGET_OS_WINDOWS)"),
+ "cv_TrackerStateEstimatorMILBoosting_TrackerMILTargetState_getFeatures_const" => ("not(target_os = \"windows\")", "!defined(OCVRS_TARGET_OS_WINDOWS)"),
+ "cv_TrackerStateEstimatorMILBoosting_TrackerMILTargetState_isTargetFg_const" => ("not(target_os = \"windows\")", "!defined(OCVRS_TARGET_OS_WINDOWS)"),
+ "cv_TrackerStateEstimatorMILBoosting_TrackerMILTargetState_setFeatures_const_MatX" => ("not(target_os = \"windows\")", "!defined(OCVRS_TARGET_OS_WINDOWS)"),
+ "cv_TrackerStateEstimatorMILBoosting_TrackerMILTargetState_setTargetFg_bool" => ("not(target_os = \"windows\")", "!defined(OCVRS_TARGET_OS_WINDOWS)"),
});
pub static ELEMENT_EXCLUDE: Lazy<RegexSet> = Lazy::new(|| RegexSet::new([
@@ -539,6 +546,10 @@ pub static ELEMENT_IGNORE: Lazy<RegexSet> = Lazy::new(|| RegexSet::new([
pub static ELEMENT_EXPORT: Lazy<HashMap<&str, ExportConfig>> = Lazy::new(|| hashmap! {
"VADisplay" => ExportConfig::default(),
"VASurfaceID" => ExportConfig::default(),
+ "cv::Mat_" => ExportConfig::default(),
+ "cv::CvFeatureParams" => ExportConfig::default(),
+ "cv::CvHaarEvaluator" => ExportConfig::default(),
+ "cv::CvHaarEvaluator::FeatureHaar" => ExportConfig::default(), // no default constructor
"cv::DetectionROI" => ExportConfig::default(),
"cv::FileNodeIterator::SeqReader" => ExportConfig::default(),
"cv::QtFont" => ExportConfig::default(),

MODIFY
binding-generator/src/type_ref.rs
binding-generator/src/type_ref.rs
@@ -67,6 +67,61 @@ pub enum Constness {
Mut,
}
+#[derive(Clone, Copy, Debug, PartialEq)]
+enum Form {
+ Declaration,
+ Reference(Option<Lifetime>, bool),
+}
+
+impl Form {
+ pub fn is_full(self) -> bool {
+ match self {
+ Form::Declaration => false,
+ Form::Reference(..) => true,
+ }
+ }
+
+ pub fn is_turbo_fish(self) -> bool {
+ match self {
+ Form::Declaration => false,
+ Form::Reference(_, turbo_fish) => turbo_fish,
+ }
+ }
+
+ pub fn recurse(self) -> Self {
+ match self {
+ Form::Declaration => {
+ self
+ },
+ Form::Reference(lt, turbo_fish) => {
+ Form::Reference(lt.map(Lifetime::next), turbo_fish)
+ },
+ }
+ }
+}
+
+#[derive(Clone, Copy, Debug, PartialEq)]
+enum CppForm<'s> {
+ Declaration,
+ Reference(&'s str, bool),
+}
+
+impl CppForm<'_> {
+ pub fn is_full(self) -> bool {
+ match self {
+ CppForm::Declaration => false,
+ CppForm::Reference(..) => true,
+ }
+ }
+
+ pub fn recurse(self) -> Self {
+ match self {
+ CppForm::Declaration => CppForm::Declaration,
+ CppForm::Reference(_name, extern_types) => CppForm::Reference("", extern_types),
+ }
+ }
+}
+
impl Constness {
pub fn is_const(self, type_ref: &TypeRef) -> bool {
match self {
@@ -892,7 +947,10 @@ impl<'tu, 'g> TypeRef<'tu, 'g> {
Kind::SmartPtr(ptr) => {
ptr.rust_localalias().into_owned()
}
- Kind::Primitive(..) | Kind::Class(..) | Kind::Enum(..)
+ Kind::Class(cls) => {
+ cls.rust_localname().into_owned()
+ }
+ Kind::Primitive(..) | Kind::Enum(..)
| Kind::Function(..) | Kind::Typedef(..) | Kind::Generic(..)
| Kind::Ignored => {
self.rust_local().into_owned()
@@ -934,7 +992,7 @@ impl<'tu, 'g> TypeRef<'tu, 'g> {
}
}
- fn rust_type_ref(&self, full: bool, lifetime: Option<Lifetime>) -> Cow<str> {
+ fn rust_type_ref(&self, form: Form) -> Cow<str> {
if self.is_string() {
return if self.is_const() {
"String" // todo implement receiving const str's
@@ -947,16 +1005,16 @@ impl<'tu, 'g> TypeRef<'tu, 'g> {
rust.into()
}
Kind::Array(elem, size) => {
- self.format_as_array(&elem.rust_type_ref(full, lifetime.map(Lifetime::next)), size).into()
+ self.format_as_array(&elem.rust_type_ref(form.recurse()), size).into()
}
Kind::StdVector(vec) => {
- vec.rust_name(full).into_owned().into()
+ vec.rust_name(form.is_full()).into_owned().into()
}
Kind::Reference(inner) if (inner.as_simple_class().is_some() || inner.is_enum()) && inner.is_const() => {
// const references to simple classes are passed by value for performance
// fixme: it kind of works now, but probably it's not the best idea
// because some functions can potentially save the pointer to the value, but it will be destroyed after function call
- inner.rust_type_ref(full, lifetime.map(Lifetime::next)).into_owned().into()
+ inner.rust_type_ref(form.recurse()).into_owned().into()
}
Kind::Pointer(inner) | Kind::Reference(inner) => {
if inner.is_void() {
@@ -965,38 +1023,40 @@ impl<'tu, 'g> TypeRef<'tu, 'g> {
cnst=self.rust_const_qual(true),
).into()
} else {
- let lt = lifetime.map_or_else(|| "".to_string(), |l| format!("{} ", l));
+ let lt = match form {
+ Form::Reference(Some(lt), ..) => format!("{} ", lt),
+ _ => "".to_string()
+ };
format!(
"&{lt}{cnst}{typ}",
cnst=self.rust_const_qual(false),
lt=lt,
- typ=inner.rust_type_ref(full, lifetime.map(Lifetime::next))
+ typ=inner.rust_type_ref(form.recurse())
).into()
}
}
Kind::SmartPtr(ptr) => {
- ptr.rust_name(full).into_owned().into()
+ ptr.rust_name(form.is_full()).into_owned().into()
}
Kind::Class(cls) => {
format!(
"{dyn}{name}{generic}",
- dyn=if full && cls.is_abstract() { "dyn " } else { "" },
- name=cls.rust_name(full),
- generic=self.rust_tpl_decl(full),
+ dyn=if form.is_full() && cls.is_abstract() { "dyn " } else { "" },
+ name=cls.rust_name(form.is_full()),
+ generic=self.rust_tpl_decl(form),
).into()
}
Kind::Enum(enm) => {
- enm.rust_name(full).into_owned().into()
+ enm.rust_name(form.is_full()).into_owned().into()
}
Kind::Typedef(decl) => {
- let mut out: String = decl.rust_name(full).into_owned();
+ let mut out: String = decl.rust_name(form.is_full()).into_owned();
let lifetime_count = decl.underlying_type_ref().rust_lifetime_count();
if lifetime_count >= 1 {
if lifetime_count >= 2 {
unimplemented!("Support for lifetime count >= 2 is not implemented yet");
}
- if let Some(lt) = lifetime.map(|x| x.to_string()) {
- out.reserve(lt.len() + 2);
+ if let Form::Reference(Some(lt), _) = form {
out.write_fmt(format_args!("<{}>", lt)).expect("Impossible");
}
}
@@ -1006,7 +1066,7 @@ impl<'tu, 'g> TypeRef<'tu, 'g> {
name.into()
}
Kind::Function(func) => {
- func.rust_name(full).into_owned().into()
+ func.rust_name(form.is_full()).into_owned().into()
}
Kind::Ignored => {
"<ignored>".into()
@@ -1015,18 +1075,19 @@ impl<'tu, 'g> TypeRef<'tu, 'g> {
}
pub fn rust_local(&self) -> Cow<str> {
- self.rust_type_ref(false, None)
+ self.rust_type_ref(Form::Declaration)
}
pub fn rust_full(&self) -> Cow<str> {
- self.rust_type_ref(true, None)
+ self.rust_type_ref(Form::Reference(None, false))
}
- pub fn rust_full_with_lifetimes(&self) -> Cow<str> {
- self.rust_type_ref(true, Some(Lifetime::default()))
+ pub fn rust_full_ext(&self, lifetimes: bool, turbofish: bool) -> Cow<str> {
+ let lifetimes = if lifetimes { Some(Lifetime::default()) } else { None };
+ self.rust_type_ref(Form::Reference(lifetimes, turbofish))
}
- pub fn rust_tpl_decl(&self, full: bool) -> String {
+ fn rust_tpl_decl(&self, form: Form) -> String {
let generic_types = self.template_specialization_args();
if !generic_types.is_empty() {
let mut constant_suffix = String::new();
@@ -1034,7 +1095,7 @@ impl<'tu, 'g> TypeRef<'tu, 'g> {
.filter_map(|t| {
match t {
TemplateArg::Typename(type_ref) => {
- Some(type_ref.rust_type_ref(full, None))
+ Some(type_ref.rust_type_ref(form.recurse()))
}
TemplateArg::Constant(literal) => {
constant_suffix += literal;
@@ -1046,7 +1107,8 @@ impl<'tu, 'g> TypeRef<'tu, 'g> {
}
})
.collect::<Vec<_>>();
- format!("{}<{}>", constant_suffix, generic_types.join(", "))
+ let fish = if form.is_turbo_fish() { "::" } else { "" };
+ format!("{cnst}{fish}<{typ}>", cnst=constant_suffix, fish=fish, typ=generic_types.join(", "))
} else {
"".to_string()
}
@@ -1187,16 +1249,16 @@ impl<'tu, 'g> TypeRef<'tu, 'g> {
format!("{mutable}{name}: {typ}", mutable=mutable, name=name, typ=typ)
}
- pub fn rust_return_func_decl(&self) -> Cow<str> {
+ pub fn rust_return_func_decl(&self, with_turbofish: bool) -> Cow<str> {
if self.is_by_ptr() {
- self.source().rust_full().into_owned().into()
+ self.source().rust_full_ext(false, with_turbofish).into_owned().into()
} else {
- self.rust_full()
+ self.rust_full_ext(false, with_turbofish)
}
}
pub fn rust_return_func_decl_wrapper(&self) -> Cow<str> {
- format!("Result<{}>", self.rust_return_func_decl()).into()
+ format!("Result<{}>", self.rust_return_func_decl(false)).into()
}
pub fn rust_return_map(&self, is_safe_context: bool) -> Cow<str> {
@@ -1210,7 +1272,7 @@ impl<'tu, 'g> TypeRef<'tu, 'g> {
format!(
".map(|ptr| {unsafety_call}{{ {typ}::from_raw(ptr) }})",
unsafety_call=unsafety_call,
- typ=self.rust_return_func_decl()
+ typ=self.rust_return_func_decl(true),
).into()
} else if self.as_pointer().map_or(false, |i| !i.is_void()) || self.as_fixed_array().is_some() {
let ptr_call = if self.is_const() { "ref" } else { "mut" };
@@ -1430,12 +1492,14 @@ impl<'tu, 'g> TypeRef<'tu, 'g> {
out.into()
}
- fn cpp_type_ref(&self, full: bool, name: &str) -> Cow<str> {
+ fn cpp_type_ref(&self, form: CppForm) -> Cow<str> {
let mut out = String::with_capacity(64);
let kind = self.kind();
if kind.is_constified() {
out.push_str(self.cpp_const_qual());
}
+ let name = match form { CppForm::Reference(name, _) => name, _ => "" };
+ let extern_types = match form { CppForm::Reference(_, extern_types) => extern_types, _ => true };
let space_name = if name.is_empty() { "".to_string() } else { format!(" {}", name) };
out.push_str(&match self.kind() {
Kind::Primitive(_, cpp) => {
@@ -1445,14 +1509,14 @@ impl<'tu, 'g> TypeRef<'tu, 'g> {
if let Some(size) = size {
format!(
"{typ}(*{name})[{size}]",
- typ=inner.cpp_type_ref(full, ""),
+ typ=inner.cpp_type_ref(form.recurse()),
name=name,
size=size,
)
} else {
format!(
"{typ}*{name}",
- typ=inner.cpp_type_ref(full, ""),
+ typ=inner.cpp_type_ref(form.recurse()),
name=space_name,
)
}
@@ -1460,46 +1524,48 @@ impl<'tu, 'g> TypeRef<'tu, 'g> {
Kind::StdVector(vec) => {
format!(
"{vec_type}<{elem_type}>{name}",
- vec_type=vec.cpp_name(full),
- elem_type=vec.element_type().cpp_type_ref(full, ""),
+ vec_type=vec.cpp_name(form.is_full()),
+ elem_type=vec.element_type().cpp_type_ref(form.recurse()),
name=space_name,
)
}
+ Kind::Reference(inner) if !extern_types => {
+ format!("{typ}&{name}", typ=inner.cpp_type_ref(form.recurse()), name=space_name)
+ }
Kind::Pointer(inner) | Kind::Reference(inner) => {
- format!("{typ}*{name}", typ=inner.cpp_type_ref(full, ""), name=space_name)
+ format!("{typ}*{name}", typ=inner.cpp_type_ref(form.recurse()), name=space_name)
}
Kind::SmartPtr(ptr) => {
format!(
"{ptr_type}<{inner_type}>{name}",
- ptr_type=ptr.cpp_name(full),
- inner_type=ptr.pointee().cpp_type_ref(full, ""),
+ ptr_type=ptr.cpp_name(form.is_full()),
+ inner_type=ptr.pointee().cpp_type_ref(form.recurse()),
name=space_name,
)
}
Kind::Class(cls) => {
- let mut out: String = cls.cpp_name(full).into_owned();
+ let mut out: String = cls.cpp_name(form.is_full()).into_owned();
if !self.is_std_string() { // fixme prevents emission of std::string<char>
- out += &self.cpp_tpl_decl(full);
+ out += &self.cpp_tpl_decl(form);
}
out + &space_name
-
}
Kind::Enum(enm) => {
- enm.cpp_name(full).into_owned() + &space_name
+ enm.cpp_name(form.is_full()).into_owned() + &space_name
}
Kind::Typedef(tdef) => {
let underlying_type = tdef.underlying_type_ref();
if underlying_type.as_reference().is_some() { // references can't be used in lvalue position
- underlying_type.cpp_type_ref(full, "").into_owned() + &space_name
+ underlying_type.cpp_type_ref(form.recurse()).into_owned() + &space_name
} else {
- tdef.cpp_name(full).into_owned() + &space_name
+ tdef.cpp_name(form.is_full()).into_owned() + &space_name
}
}
Kind::Generic(generic_name) => {
generic_name + &space_name
}
Kind::Function(func) => {
- func.cpp_name(full).into_owned() + &space_name
+ func.cpp_name(form.is_full()).into_owned() + &space_name
}
Kind::Ignored => {
"<ignored>".to_string() + &space_name
@@ -1509,29 +1575,29 @@ impl<'tu, 'g> TypeRef<'tu, 'g> {
}
pub fn cpp_local(&self) -> Cow<str> {
- self.cpp_local_with_name("")
- }
-
- pub fn cpp_local_with_name(&self, name: &str) -> Cow<str> {
- self.cpp_type_ref(false, name)
+ self.cpp_type_ref(CppForm::Declaration)
}
pub fn cpp_full(&self) -> Cow<str> {
- self.cpp_full_with_name("")
+ self.cpp_type_ref(CppForm::Reference("", true))
}
pub fn cpp_full_with_name(&self, name: &str) -> Cow<str> {
- self.cpp_type_ref(true, name)
+ self.cpp_type_ref(CppForm::Reference(name, true))
+ }
+
+ pub fn cpp_full_native(&self, name: &str) -> Cow<str> {
+ self.cpp_type_ref(CppForm::Reference(name, false))
}
- fn cpp_tpl_decl(&self, full: bool) -> String {
+ fn cpp_tpl_decl(&self, form: CppForm) -> String {
let generic_types = self.template_specialization_args();
if !generic_types.is_empty() {
let generic_types = generic_types.iter()
.filter_map(|t| {
match t {
TemplateArg::Typename(type_ref) => {
- Some(type_ref.cpp_type_ref(full, ""))
+ Some(type_ref.cpp_type_ref(form.recurse()))
}
TemplateArg::Constant(literal) => {
Some(literal.into())

MODIFY
binding-generator/src/typedef.rs
binding-generator/src/typedef.rs
@@ -137,7 +137,7 @@ impl GeneratedElement for Typedef<'_, '_> {
"debug" => get_debug(self).into(),
"rust_local" => self.rust_localname(),
"generic_args" => generic_args.into(),
- "definition" => underlying_type.rust_full_with_lifetimes(),
+ "definition" => underlying_type.rust_full_ext(true, false),
})
}
}

MODIFY
build.rs
build.rs
@@ -917,7 +917,6 @@ fn make_modules(opencv_dir_as_string: &str) -> Result<()> {
"opencv_modules",
"optflow",
"rgbd",
- "tracking",
].iter().copied());
let modules: Vec<String> = glob(&format!("{}/*.hpp", opencv_dir_as_string))?

MODIFY
src/manual/core/mat.rs
src/manual/core/mat.rs
use std::{
+ convert::TryInto,
ffi::c_void,
fmt,
- marker::PhantomData,
ops::Deref,
slice,
};
use libc::size_t;
+pub use mat_::*;
+
use crate::{
core::{
self,
@@ -30,6 +32,8 @@ use crate::{
sys,
};
+mod mat_;
+
/// This sealed trait is implemented for types that are valid to use as Mat elements
pub trait DataType: Copy + private::Sealed {
fn depth() -> i32;
@@ -114,41 +118,6 @@ data_type!(core::Rect2i, core::CV_32S, 4);
data_type!(core::Rect2f, core::CV_32F, 4);
data_type!(core::Rect2d, core::CV_64F, 4);
-/// [docs.opencv.org](https://docs.opencv.org/master/df/dfc/classcv_1_1Mat__.html)
-pub struct Mat_<T> {
- inner: Mat,
- _type: PhantomData<T>,
-}
-
-impl<T: DataType> Mat_<T> {
- pub fn from_mat(s: Mat) -> Result<Self> {
- match_format::<T>(s.typ()?)
- .map(|_| Mat_ { inner: s, _type: PhantomData })
- }
-
- #[inline(always)]
- pub fn at(&self, i0: i32) -> Result<&T> {
- match_dims(self, 2)
- .and_then(|_| match_total(self, i0))
- .and_then(|_| unsafe { self.at_unchecked(i0) })
- }
-
- #[inline(always)]
- pub fn at_mut(&mut self, i0: i32) -> Result<&mut T> {
- match_dims(self, 2)
- .and_then(|_| match_total(self, i0))?;
- unsafe { self.at_unchecked_mut(i0) }
- }
-
- pub fn into_mat(self) -> Mat {
- self.inner
- }
-}
-
-impl<T: DataType> MatTrait for Mat_<T> {
- fn as_raw_Mat(&self) -> *const c_void { self.inner.as_raw_Mat() }
- fn as_raw_mut_Mat(&mut self) -> *mut c_void { self.inner.as_raw_mut_Mat() }
-}
#[inline(always)]
unsafe fn convert_ptr<T>(r: &u8) -> &T {
@@ -263,8 +232,8 @@ impl Mat {
Ok(out)
}
- pub fn into_typed<T: DataType>(self) -> Result<Mat_<T>> where Self: Sized {
- Mat_::from_mat(self)
+ pub fn try_into_typed<T: DataType>(self) -> Result<Mat_<T>> where Self: Sized {
+ self.try_into()
}
}

ADD
src/manual/core/mat/mat_.rs
+use std::{
+ convert::TryFrom,
+ ffi::c_void,
+ fmt,
+ marker::PhantomData,
+};
+
+use crate::{
+ core::{Mat, MatTrait},
+ Error,
+ Result,
+ traits::{Boxed, OpenCVType, OpenCVTypeExternContainer},
+};
+
+use super::{DataType, match_dims, match_format, match_is_continuous, match_total, MatTraitManual};
+
+/// [docs.opencv.org](https://docs.opencv.org/master/df/dfc/classcv_1_1Mat__.html)
+///
+/// This struct is freely convertible into and from `Mat` using `into` and `try_from` methods. You might want
+/// to convert `Mat` to `Mat_` before calling typed methods (like `at`, `data_typed`) when more performance is
+/// required because this way you will skip the data type checks (still WIP, not all methods are covered).
+pub struct Mat_<T> {
+ inner: Mat,
+ _type: PhantomData<T>,
+}
+
+impl<T: DataType> TryFrom<Mat> for Mat_<T> {
+ type Error = Error;
+
+ #[inline(always)]
+ fn try_from(mat: Mat) -> Result<Self, Self::Error> {
+ match_format::<T>(mat.typ()?)
+ .map(|_| Self { inner: mat, _type: PhantomData })
+ }
+}
+
+impl<T: DataType> From<Mat_<T>> for Mat {
+ #[inline]
+ fn from(s: Mat_<T>) -> Self {
+ s.inner
+ }
+}
+
+impl<T: DataType> Mat_<T> {
+ #[inline]
+ pub fn into_untyped(self) -> Mat {
+ self.into()
+ }
+
+ #[inline]
+ pub fn as_raw_Mat_(&self) -> *const c_void {
+ #![allow(non_snake_case)]
+ self.as_raw_Mat()
+ }
+
+ #[inline]
+ pub fn as_raw_mut_Mat_(&mut self) -> *mut c_void {
+ #![allow(non_snake_case)]
+ self.as_raw_mut_Mat()
+ }
+
+ #[inline(always)]
+ pub fn at(&self, i0: i32) -> Result<&T> {
+ match_dims(self, 2)
+ .and_then(|_| match_total(self, i0))
+ .and_then(|_| unsafe { self.at_unchecked(i0) })
+ }
+
+ #[inline(always)]
+ pub fn at_mut(&mut self, i0: i32) -> Result<&mut T> {
+ match_dims(self, 2)
+ .and_then(|_| match_total(self, i0))?;
+ unsafe { self.at_unchecked_mut(i0) }
+ }
+
+ pub fn data_typed(&self) -> Result<&[T]> {
+ match_is_continuous(self)
+ .and_then(|_| unsafe { self.data_typed_unchecked() })
+ }
+
+ pub fn data_typed_mut(&mut self) -> Result<&mut [T]> {
+ match_is_continuous(self)?;
+ unsafe { self.data_typed_unchecked_mut() }
+ }
+}
+
+impl<T> MatTrait for Mat_<T> {
+ #[inline]
+ fn as_raw_Mat(&self) -> *const c_void { self.inner.as_raw_Mat() }
+
+ #[inline]
+ fn as_raw_mut_Mat(&mut self) -> *mut c_void { self.inner.as_raw_mut_Mat() }
+}
+
+impl<T> Boxed for Mat_<T> {
+ #[inline]
+ unsafe fn from_raw(ptr: *mut c_void) -> Self {
+ Self { inner: Mat::from_raw(ptr), _type: PhantomData }
+ }
+
+ #[inline]
+ fn into_raw(self) -> *mut c_void {
+ self.inner.into_raw()
+ }
+
+ #[inline]
+ fn as_raw(&self) -> *const c_void {
+ self.inner.as_raw()
+ }
+
+ #[inline]
+ fn as_raw_mut(&mut self) -> *mut c_void {
+ self.inner.as_raw_mut()
+ }
+}
+
+impl<T> OpenCVType<'_> for Mat_<T> {
+ type Owned = Self;
+ type Arg = Self;
+ type ExternReceive = *mut c_void;
+ type ExternContainer = Self;
+
+ #[inline]
+ fn opencv_into_extern_container(self) -> Result<Self::ExternContainer> {
+ Ok(self)
+ }
+
+ #[inline]
+ fn opencv_into_extern_container_nofail(self) -> Self::ExternContainer {
+ self
+ }
+
+ #[inline]
+ unsafe fn opencv_from_extern(s: Self::ExternReceive) -> Self::Owned {
+ Self::from_raw(s)
+ }
+}
+
+impl<T> OpenCVTypeExternContainer for Mat_<T> {
+ type ExternSend = *const c_void;
+ type ExternSendMut = *mut c_void;
+
+ #[inline]
+ fn opencv_to_extern(&self) -> Self::ExternSend {
+ self.as_raw()
+ }
+
+ #[inline]
+ fn opencv_to_extern_mut(&mut self) -> Self::ExternSendMut {
+ self.as_raw_mut()
+ }
+}
+
+impl<T> fmt::Debug for Mat_<T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ self.inner.fmt(f)
+ }
+}

MODIFY
tests/mat.rs
tests/mat.rs
@@ -475,13 +475,13 @@ fn mat_locate_roi() -> Result<()> {
#[test]
fn mat_convert() -> Result<()> {
let mat = Mat::from_slice(&[1, 2, 3, 4])?;
- let mut mat_ = mat.clone()?.into_typed::<i32>()?;
- assert_eq!(3, *mat_.get(2)?);
- *mat_.get_mut(3)? = 8;
- assert_eq!(8, *mat_.get(3)?);
+ let mut mat_ = mat.clone()?.try_into_typed::<i32>()?;
+ assert_eq!(3, *mat_.at(2)?);
+ *mat_.at_mut(3)? = 8;
+ assert_eq!(8, *mat_.at(3)?);
assert_eq!(mat.typ()?, mat_.typ()?);
assert_eq!(mat.size()?, mat_.size()?);
- let mat_back = mat_.into_mat();
+ let mat_back = mat_.into_untyped();
assert_eq!(mat.size()?, mat_back.size()?);
Ok(())
}

ADD
tests/tracking.rs
+#![cfg(feature = "contrib")]
+
+use opencv::{
+ prelude::*,
+ Result,
+ tracking::TrackerSamplerPF_Params,
+};
+use opencv::core::Scalar;
+
+#[test]
+fn typed_mat() -> Result<()> {
+ let mut params = TrackerSamplerPF_Params::default()?;
+ assert_eq!(&[15., 15., 15., 15.], params.std().data_typed()?);
+ let mat = Mat::new_rows_cols_with_default(1, 4, f64::typ(), Scalar::all(8.))?.try_into_typed::<f64>()?;
+ let mat_src = mat.clone()?.try_into_typed::<f64>()?;
+ params.set_std(mat);
+ let mat = params.std();
+ assert_eq!(mat.size()?, mat_src.size()?);
+ assert_eq!(mat.data_typed()?, mat_src.data_typed()?);
+ Ok(())
+}

Enable tracking module

Also improve Mat_ usability