Add basic Mat_ type
MODIFY
binding-generator/src/class.rs
binding-generator/src/class.rs
@@ -498,14 +498,13 @@ impl Element for Class<'_, '_> {
fn is_excluded(&self) -> bool {
DefaultElement::is_excluded(self)
|| match self.kind() { Kind::Excluded => true, _ => false }
- || !self.is_definition() // prevent generation of spurious empty imports
}
fn is_ignored(&self) -> bool {
DefaultElement::is_ignored(self)
|| self.is_template()
|| self.is_template_specialization() && !settings::IMPLEMENTED_GENERICS.contains(self.cpp_fullname().as_ref())
- || !self.is_template_specialization() && self.entity.get_definition().is_none()
+ || !self.is_template_specialization() && !self.is_definition()
}
fn is_system(&self) -> bool {

MODIFY
binding-generator/src/generator.rs
binding-generator/src/generator.rs
@@ -229,14 +229,20 @@ impl<V: GeneratorVisitor> OpenCVWalker<'_, V> {
fn process_typedef<'tu>(visitor: &mut impl GeneratorVisitor, gen_env: &mut GeneratorEnv<'tu>, typedef_decl: Entity<'tu>) {
let typedef = Typedef::new(typedef_decl, gen_env);
- if gen_env.get_export_config(typedef_decl).is_some()
+ let mut export = gen_env.get_export_config(typedef_decl).is_some()
// we need to have a typedef even if it's not exported for e.g. cv::Size
- || settings::DATA_TYPES.contains(typedef.cpp_fullname().as_ref())
- || typedef.underlying_type_ref().as_vector().map_or(false, |v| settings::DATA_TYPES.contains(v.element_type().cpp_full().as_ref()))
- || typedef.underlying_type_ref().as_function().is_some() {
- if !typedef.is_excluded() {
- visitor.visit_typedef(typedef)
+ || typedef.type_ref().is_data_type();
+ export = export || {
+ let underlying_type = typedef.underlying_type_ref();
+ underlying_type.as_function().is_some()
+ || if let Some(templ) = underlying_type.as_template() {
+ settings::IMPLEMENTED_GENERICS.contains(templ.cpp_fullname().as_ref())
+ } else {
+ false
}
+ };
+ if export && !typedef.is_excluded() {
+ visitor.visit_typedef(typedef)
}
}
}

MODIFY
binding-generator/src/generator_env.rs
binding-generator/src/generator_env.rs
@@ -188,7 +188,11 @@ impl<'tu> GeneratorEnv<'tu> {
let id = entity.usr();
memo_map(&self.class_kind_cache, id.as_ref(), || {
if let Some(range) = entity.get_range() {
- let name_ranges = entity.get_name_ranges();
+ let name_ranges = if let Some(tpl_decl) = entity.get_template() {
+ tpl_decl
+ } else {
+ entity
+ }.get_name_ranges();
if !name_ranges.is_empty() {
let file_location = range.get_start().get_file_location();
if let Some(file) = file_location.file {

MODIFY
binding-generator/src/settings.rs
binding-generator/src/settings.rs
@@ -567,14 +567,6 @@ pub static ELEMENT_EXPORT: Lazy<HashMap<&str, ExportConfig>> = Lazy::new(|| hash
"cv::dnn::Model" => ExportConfig::default(),
"cv::dnn::Net" => ExportConfig::default(), // incorrectly marked as simple
"cv::ocl::Device" => ExportConfig::default(),
-
- // override simple
- "cv::Point3_" => ExportConfig::simple(),
- "cv::Point_" => ExportConfig::simple(),
- "cv::Rect_" => ExportConfig::simple(),
- "cv::Scalar_" => ExportConfig::simple(),
- "cv::Size_" => ExportConfig::simple(),
- "cv::Vec" => ExportConfig::simple(),
});
/// set of functions that should have unsafe in their declaration, element is Func.identifier()
@@ -727,12 +719,13 @@ pub static DATA_TYPES: Lazy<BTreeSet<&str>> = Lazy::new(|| btreeset! {
});
pub static IMPLEMENTED_GENERICS: Lazy<HashSet<&str>> = Lazy::new(|| hashset! {
- "cv::Vec",
- "cv::Scalar_",
- "cv::Point_",
+ "cv::Mat_",
"cv::Point3_",
- "cv::Size_",
+ "cv::Point_",
"cv::Rect_",
+ "cv::Scalar_",
+ "cv::Size_",
+ "cv::Vec",
});
#[derive(Debug)]

MODIFY
binding-generator/src/type_ref.rs
binding-generator/src/type_ref.rs
use std::{
borrow::Cow,
cmp,
- collections::HashSet,
fmt,
};
use clang::{Entity, EntityKind, Type, TypeKind};
-use maplit::hashset;
use once_cell::{
sync::Lazy,
unsync::Lazy as UnsyncLazy,
@@ -259,25 +257,16 @@ impl<'tu, 'g> TypeRef<'tu, 'g> {
}
TypeKind::Typedef => {
- static IGNORED_SYSTEM_TYPEDEFS: Lazy<HashSet<&str>> = Lazy::new(|| hashset! {
- "FILE",
- "const_iterator",
- "ifstream",
- "ofstream",
- "ostream",
- });
let decl = self.type_ref.get_declaration().expect("Can't get typedef declaration");
- let decl_name = decl.get_name().expect("Can't get typedef name");
- if let Some(&(rust, cpp)) = settings::PRIMITIVE_TYPEDEFS.get(decl_name.as_str()) {
+ let decl_name = decl.cpp_fullname();
+ if let Some(&(rust, cpp)) = settings::PRIMITIVE_TYPEDEFS.get(decl_name.as_ref()) {
Kind::Primitive(rust, cpp)
}
else if decl.is_system() {
- if decl_name == "string" {
+ if decl_name.starts_with("std::") && decl_name.ends_with("::string") {
Kind::Class(Class::new(decl, self.gen_env))
- } else if IGNORED_SYSTEM_TYPEDEFS.contains(decl_name.as_str()) {
- Kind::Ignored
} else {
- unreachable!("Unknown system typedef, don't know how to handle that: {:#?}", decl)
+ Kind::Ignored
}
} else {
Kind::Typedef(Typedef::new(decl, self.gen_env))
@@ -432,6 +421,17 @@ impl<'tu, 'g> TypeRef<'tu, 'g> {
}
}
+ pub fn as_template(&self) -> Option<Class<'tu, 'g>> {
+ match self.base().kind() {
+ Kind::Class(cls) => {
+ cls.as_template()
+ }
+ _ => {
+ None
+ }
+ }
+ }
+
pub fn is_generic(&self) -> bool {
match self.base().kind() {
Kind::Generic(..) => {
@@ -772,6 +772,10 @@ impl<'tu, 'g> TypeRef<'tu, 'g> {
!self.is_const() && (self.as_reference().is_some() || self.as_pointer().map_or(false, |t| t.is_string()))
}
+ pub fn is_data_type(&self) -> bool {
+ settings::DATA_TYPES.contains(self.cpp_full().as_ref())
+ }
+
pub fn rust_const_qual(&self, pointer: bool) -> &'static str {
if self.is_const() {
if pointer {

MODIFY
binding-generator/src/typedef.rs
binding-generator/src/typedef.rs
@@ -16,6 +16,7 @@ use crate::{
GeneratorEnv,
get_debug,
IteratorExt,
+ settings,
StrExt,
type_ref::Kind,
TypeRef,
@@ -33,6 +34,10 @@ impl<'tu, 'g> Typedef<'tu, 'g> {
Self { entity, gen_env }
}
+ pub fn type_ref(&self) -> TypeRef<'tu, 'g> {
+ TypeRef::new(self.entity.get_type().expect("Can't get typedef type"), self.gen_env)
+ }
+
pub fn underlying_type_ref(&self) -> TypeRef<'tu, 'g> {
TypeRef::new_ext(
self.entity.get_typedef_underlying_type().expect("Can't get typedef underlying type"),
@@ -50,6 +55,11 @@ impl<'tu> EntityElement<'tu> for Typedef<'tu, '_> {
}
impl Element for Typedef<'_, '_> {
+ fn is_excluded(&self) -> bool {
+ DefaultElement::is_excluded(self)
+ || settings::PRIMITIVE_TYPEDEFS.contains_key(self.cpp_fullname().as_ref())
+ }
+
fn is_ignored(&self) -> bool {
DefaultElement::is_ignored(self) || self.underlying_type_ref().is_ignored()
}

MODIFY
binding-generator/src/vector.rs
binding-generator/src/vector.rs
@@ -19,7 +19,6 @@ use crate::{
EntityElement,
GeneratedElement,
GeneratorEnv,
- settings,
StrExt,
TypeRef,
};
@@ -179,7 +178,7 @@ impl GeneratedElement for Vector<'_, '_> {
inherent_methods += &INHERENT_COPY_NON_BOOL_TPL.interpolate(&inter_vars);
}
}
- if settings::DATA_TYPES.contains(self.element.cpp_full().as_ref()) || self.element.as_vector().map_or(false, |v| settings::DATA_TYPES.contains(v.element_type().cpp_full().as_ref())) {
+ if self.element.is_data_type() || self.element.as_vector().map_or(false, |v| v.element_type().is_data_type()) {
impls += &INPUT_OUTPUT_ARRAY_TPL.interpolate(&inter_vars);
}
@@ -249,7 +248,7 @@ impl GeneratedElement for Vector<'_, '_> {
exports += &METHODS_COPY_NON_BOOL_TPL.interpolate(&inter_vars);
}
}
- if settings::DATA_TYPES.contains(self.element.cpp_full().as_ref()) || self.element.as_vector().map_or(false, |v| settings::DATA_TYPES.contains(v.element_type().cpp_full().as_ref())) {
+ if self.element.is_data_type() || self.element.as_vector().map_or(false, |v| v.element_type().is_data_type()) {
exports += &INPUT_OUTPUT_ARRAY_TPL.interpolate(&inter_vars);
}
inter_vars.insert("exports", exports.into());

MODIFY
src/manual/core/mat.rs
src/manual/core/mat.rs
use std::{
ffi::c_void,
fmt,
+ marker::PhantomData,
ops::Deref,
slice,
};
@@ -112,6 +113,43 @@ 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_mat_format::<T, _>(&s)
+ .map(|_| Mat_ { inner: s, _type: PhantomData })
+ }
+
+ #[inline(always)]
+ pub fn get(&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 get_mut(&mut self, i0: i32) -> Result<&mut T> {
+ match_dims(self, 2)
+ .and_then(|_| match_total(self, i0))?;
+ unsafe { self.at_mut_unchecked(i0) }
+ }
+
+ pub fn into_mat(self) -> Mat {
+ self.inner
+ }
+}
+
+impl<T: DataType> MatTrait for Mat_<T> {
+ fn as_raw_Mat(&self) -> *mut c_void {
+ self.inner.as_raw_Mat()
+ }
+}
+
#[inline(always)]
fn convert_ptr<T>(r: &u8) -> &T {
unsafe { &*(r as *const _ as *const T) }
@@ -234,6 +272,10 @@ impl Mat {
}
Ok(out)
}
+
+ pub fn into_typed<T: DataType>(self) -> Result<Mat_<T>> where Self: Sized {
+ Mat_::from_mat(self)
+ }
}
pub(crate) mod mat_forward {

MODIFY
src/manual/core/vec.rs
src/manual/core/vec.rs
@@ -22,6 +22,7 @@ mod scalar {
macro_rules! vec_impl {
($type: ident, $count: expr, $type_trait: ident) => {
+ /// [docs.opencv.org](https://docs.opencv.org/master/d6/dcf/classcv_1_1Vec.html)
#[repr(C)]
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
pub struct $type<T: $type_trait>(pub [T; $count]);

MODIFY
tests/mat.rs
tests/mat.rs
@@ -472,3 +472,17 @@ fn mat_locate_roi() -> Result<()> {
assert_eq!(ofs, Point::new(1, 0));
Ok(())
}
+
+#[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)?);
+ assert_eq!(mat.typ()?, mat_.typ()?);
+ assert_eq!(mat.size()?, mat_.size()?);
+ let mat_back = mat_.into_mat();
+ assert_eq!(mat.size()?, mat_back.size()?);
+ Ok(())
+}

Add basic Mat_ type