Add support for generation of operator* (as mul and as deref)
Fixes
MODIFY
binding-generator/src/func.rs
binding-generator/src/func.rs
@@ -38,14 +38,35 @@ use crate::{
pub enum OperatorKind {
Unsupported,
Index,
+ Add,
+ Sub,
+ Mul,
+ Div,
+ Deref,
}
-impl From<&str> for OperatorKind {
- fn from(s: &str) -> Self {
- match s.trim() {
+impl OperatorKind {
+ pub fn new(token: &str, arg_count: usize) -> Self {
+ match token.trim() {
"[]" => {
OperatorKind::Index
}
+ "+" => {
+ OperatorKind::Add
+ }
+ "-" => {
+ OperatorKind::Sub
+ }
+ "*" => {
+ if arg_count == 0 {
+ OperatorKind::Deref
+ } else {
+ OperatorKind::Mul
+ }
+ }
+ "/" => {
+ OperatorKind::Div
+ }
_ => {
OperatorKind::Unsupported
},
@@ -110,7 +131,8 @@ impl<'tu, 'g> Func<'tu, 'g> {
match self.entity.get_kind() {
EntityKind::FunctionDecl => {
if let Some(operator) = self.entity.cpp_localname().strip_str_prefix(OPERATOR) {
- Kind::FunctionOperator(operator.into())
+ let arg_count = self.entity.get_arguments().map_or(0, |v| v.len());
+ Kind::FunctionOperator(OperatorKind::new(operator.trim(), arg_count))
} else {
Kind::Function
}
@@ -130,7 +152,8 @@ impl<'tu, 'g> Func<'tu, 'g> {
Kind::StaticMethod(class)
} else {
if let Some(operator) = self.entity.cpp_localname().strip_str_prefix(OPERATOR) {
- Kind::InstanceOperator(class, operator.into())
+ let arg_count = self.entity.get_arguments().map_or(0, |v| v.len());
+ Kind::InstanceOperator(class, OperatorKind::new(operator.trim(), arg_count))
} else {
Kind::InstanceMethod(class)
}
@@ -802,6 +825,9 @@ impl Element for Func<'_, '_> {
} else if let Some((.., kind)) = self.as_operator() {
if cpp_name.starts_with("operator") {
match kind {
+ OperatorKind::Unsupported => {
+ cpp_name
+ }
OperatorKind::Index => {
if self.is_const() {
"get".into()
@@ -809,8 +835,24 @@ impl Element for Func<'_, '_> {
"get_mut".into()
}
}
- OperatorKind::Unsupported => {
- cpp_name
+ OperatorKind::Add => {
+ "add".into()
+ }
+ OperatorKind::Sub => {
+ "sub".into()
+ }
+ OperatorKind::Mul => {
+ "mul".into()
+ }
+ OperatorKind::Div => {
+ "div".into()
+ }
+ OperatorKind::Deref => {
+ if self.is_const() {
+ "try_deref".into()
+ } else {
+ "try_deref_mut".into()
+ }
}
}
} else {

MODIFY
binding-generator/src/settings.rs
binding-generator/src/settings.rs
@@ -217,6 +217,40 @@ pub static FUNC_RENAME: Lazy<HashMap<&str, &str>> = Lazy::new(|| {
"cv_ocl_Kernel_set_int_const_UMatX" => "+_umat",
"cv_ocl_ProgramSource_ProgramSource_const_StringX" => "from_str",
"cv_ocl_Program_getPrefix_const_StringX" => "+_build_flags",
+ "cv_operatorA_const_MatExprX_const_MatExprX" => "+_matexpr_matexpr",
+ "cv_operatorA_const_MatExprX_const_MatX" => "+_matexpr_mat",
+ "cv_operatorA_const_MatExprX_const_ScalarX" => "+_matexpr_scalar",
+ "cv_operatorA_const_MatX_const_MatExprX" => "+_mat_matexpr",
+ "cv_operatorA_const_MatX_const_MatX" => "+_mat_mat",
+ "cv_operatorA_const_MatX_const_ScalarX" => "+_mat_scalar",
+ "cv_operatorA_const_ScalarX_const_MatExprX" => "+_scalar_matexpr",
+ "cv_operatorA_const_ScalarX_const_MatX" => "+_scalar_mat",
+ "cv_operatorD_const_MatExprX_const_MatExprX" => "+_matexpr_matexpr",
+ "cv_operatorD_const_MatExprX_const_MatX" => "+_matexpr_mat",
+ "cv_operatorD_const_MatExprX_double" => "+_matexpr_f64",
+ "cv_operatorD_const_MatX_const_MatExprX" => "+_mat_matexpr",
+ "cv_operatorD_const_MatX_const_MatX" => "+_mat_mat",
+ "cv_operatorD_const_MatX_double" => "+_mat_f64",
+ "cv_operatorD_double_const_MatExprX" => "+_f64_matexpr",
+ "cv_operatorD_double_const_MatX" => "+_f64_mat",
+ "cv_operatorS_const_MatExprX" => "+_matexpr",
+ "cv_operatorS_const_MatExprX_const_MatExprX" => "+_matexpr_matexpr",
+ "cv_operatorS_const_MatExprX_const_MatX" => "+_matexpr_mat",
+ "cv_operatorS_const_MatExprX_const_ScalarX" => "+_matexpr_scalar",
+ "cv_operatorS_const_MatX" => "+_mat",
+ "cv_operatorS_const_MatX_const_MatExprX" => "+_mat_matexpr",
+ "cv_operatorS_const_MatX_const_MatX" => "+_mat_mat",
+ "cv_operatorS_const_MatX_const_ScalarX" => "+_mat_scalar",
+ "cv_operatorS_const_ScalarX_const_MatExprX" => "+_scalar_matexpr",
+ "cv_operatorS_const_ScalarX_const_MatX" => "+_scalar_mat",
+ "cv_operatorX_const_MatExprX_const_MatExprX" => "+_matexpr_matexpr",
+ "cv_operatorX_const_MatExprX_const_MatX" => "+_matexpr_mat",
+ "cv_operatorX_const_MatExprX_double" => "+_matexpr_f64",
+ "cv_operatorX_const_MatX_const_MatExprX" => "+_mat_matexpr",
+ "cv_operatorX_const_MatX_const_MatX" => "+_mat_mat",
+ "cv_operatorX_const_MatX_double" => "+_mat_f64",
+ "cv_operatorX_double_const_MatExprX" => "+_f64_matexpr",
+ "cv_operatorX_double_const_MatX" => "+_f64_mat",
"cv_read_FileNode_Range_Range" => "+_range",
"cv_read_FileNode_VectorOfDMatch_VectorOfDMatch" => "+_dmatch_vec",
"cv_read_FileNode_VectorOfKeyPoint_VectorOfKeyPoint" => "+_keypoint_vec",

MODIFY
binding-generator/src/string_ext.rs
binding-generator/src/string_ext.rs
@@ -207,6 +207,9 @@ impl StringExt for String {
self.replace_in_place("[", "_");
self.replace_in_place("]", "_");
self.replace_in_place("::", "_");
+ self.replace_in_place("+", "A");
+ self.replace_in_place("-", "S");
+ self.replace_in_place("/", "D");
}
}

MODIFY
src/manual/core/mat.rs
src/manual/core/mat.rs
@@ -6,7 +6,7 @@ use std::{
slice,
};
-use libc::{c_uchar, size_t};
+use libc::size_t;
use crate::{
core::{
@@ -700,20 +700,11 @@ pub trait MatConstIteratorTraitManual: MatConstIteratorTrait {
fn current<T: DataType>(&self) -> Result<&T> {
match_format::<T>(self.typ())?;
if self.has_elements() {
- unsafe { self.current_unchecked() }
+ self.try_deref().map(|ptr| unsafe { convert_ptr(ptr) })
} else {
Err(Error::new(core::StsOutOfRange, "MatConstIterator doesn't have any more elements".to_owned()))
}
}
-
- #[inline]
- unsafe fn current_unchecked<T: DataType>(&self) -> Result<&T> {
- extern "C" { fn cv_manual_MatConstIterator_current_unchecked(instance: *mut c_void) -> *const c_uchar; }
- cv_manual_MatConstIterator_current_unchecked(self.as_raw_MatConstIterator())
- .as_ref()
- .map(|ptr| convert_ptr(ptr))
- .ok_or_else(|| Error::new(core::StsNullPtr, "Function returned Null pointer".to_string()))
- }
}
impl<T: MatConstIteratorTrait> MatConstIteratorTraitManual for T {}

MODIFY
src_cpp/manual-core.cpp
src_cpp/manual-core.cpp
@@ -80,10 +80,6 @@ extern "C" {
return instance->ptr != instance->sliceEnd;
}
- const unsigned char* cv_manual_MatConstIterator_current_unchecked(const cv::MatConstIterator* instance) {
- return instance->ptr;
- }
-
Result<void*> cv_InputArray_input_array(cv::_InputArray* instance) { return ocvrs_input_array(instance); }
Result<void*> cv_OutputArray_output_array(cv::_OutputArray* instance) { return ocvrs_output_array(instance); }
Result<void*> cv_InputOutputArray_input_output_array(cv::_InputOutputArray* instance) { return ocvrs_input_output_array(instance); }

MODIFY
tests/mat.rs
tests/mat.rs
@@ -30,7 +30,7 @@ fn mat_create() -> Result<()> {
let mut mat = Mat::default()?;
unsafe { mat.create_rows_cols(10, 10, u16::typ())? };
assert!(mat.is_allocated());
- mat.set(Scalar::all(7.))?;
+ mat.set(Scalar::from(7.))?;
assert_eq!(7, *mat.at_2d::<u16>(0, 0)?);
assert_eq!(7, *mat.at_2d::<u16>(3, 3)?);
assert_eq!(7, *mat.at_2d::<u16>(9, 9)?);
@@ -185,7 +185,7 @@ fn mat_at_1d() -> Result<()> {
#[test]
fn mat_2d_i0_is_rows_i1_is_cols() -> Result<()> {
// Just a sanity check about which Mat dimension corresponds to which in Size
- let mat = Mat::new_size_with_default(Size::new(6, 5), f32::typ(), Scalar::all(1.23))?;
+ let mat = Mat::new_size_with_default(Size::new(6, 5), f32::typ(), Scalar::from(1.23))?;
let size = mat.size()?;
assert_eq!(size.width, 6);
assert_eq!(size.height, 5);
@@ -194,7 +194,7 @@ fn mat_2d_i0_is_rows_i1_is_cols() -> Result<()> {
#[test]
fn mat_at_2d() -> Result<()> {
- let mut mat = Mat::new_rows_cols_with_default(100, 100, f32::typ(), Scalar::all(1.23))?;
+ let mut mat = Mat::new_rows_cols_with_default(100, 100, f32::typ(), Scalar::from(1.23))?;
assert_eq!(*mat.at_2d::<f32>(0, 0)?, 1.23);
*mat.at_2d_mut::<f32>(0, 0)? = 1.;
assert_eq!(*mat.at_2d::<f32>(0, 0)?, 1.);
@@ -226,7 +226,7 @@ fn mat_at_2d_multichannel() -> Result<()> {
#[test]
fn mat_at_row() -> Result<()> {
- let mut mat = Mat::new_rows_cols_with_default(100, 100, f32::typ(), Scalar::all(1.23))?;
+ let mut mat = Mat::new_rows_cols_with_default(100, 100, f32::typ(), Scalar::from(1.23))?;
let row = mat.at_row::<f32>(0)?;
assert_eq!(row.len(), 100);
@@ -288,7 +288,7 @@ fn mat_vec() -> Result<()> {
dims.push(3);
dims.push(3);
dims.push(3);
- let mut mat = Mat::new_nd_vec_with_default(&dims, f64::typ(), Scalar::all(2.))?;
+ let mut mat = Mat::new_nd_vec_with_default(&dims, f64::typ(), Scalar::from(2.))?;
*mat.at_3d_mut::<f64>(1, 1, 1)? = 10.;
assert_eq!(3, mat.dims());
if mat.to_vec_2d::<f64>().is_ok() {
@@ -371,8 +371,8 @@ fn mat_continuous() -> Result<()> {
#[test]
fn mat_operations() -> Result<()> {
let mut src = VectorOfMat::new();
- src.push(Mat::new_rows_cols_with_default(1, 3, u8::typ(), Scalar::all(1.))?);
- src.push(Mat::new_rows_cols_with_default(1, 3, u8::typ(), Scalar::all(2.))?);
+ src.push(Mat::new_rows_cols_with_default(1, 3, u8::typ(), Scalar::from(1.))?);
+ src.push(Mat::new_rows_cols_with_default(1, 3, u8::typ(), Scalar::from(2.))?);
let mut merged = Mat::default()?;
core::merge(&src, &mut merged)?;
assert_eq!(merged.typ()?, Vec2b::typ());
@@ -485,3 +485,34 @@ fn mat_convert() -> Result<()> {
assert_eq!(mat.size()?, mat_back.size()?);
Ok(())
}
+
+#[test]
+fn mat_mul() -> Result<()> {
+ {
+ let expr = Mat::ones(1, 5, f64::typ())?;
+ let res = core::mul_matexpr_f64(&expr, 4.)?.to_mat()?;
+ assert_eq!(res.typ()?, f64::typ());
+ assert_eq!(res.data_typed::<f64>()?, &[4., 4., 4., 4., 4.]);
+ }
+ {
+ let expr = Mat::new_rows_cols_with_default(2, 3, i32::typ(), Scalar::from(9.))?;
+ let res = core::sub_mat_scalar(&expr, Scalar::from(5.))?.to_mat()?;
+ assert_eq!(res.typ()?, i32::typ());
+ assert_eq!(res.data_typed::<i32>()?, &[4, 4, 4, 4, 4, 4]);
+ }
+ {
+ let mat1 = Mat::from_slice_2d(&[[1f32, 2., 3.], [4., 5., 6.]])?;
+ let mat2 = Mat::from_slice_2d(&[[7f32, 8.], [9., 10.], [11., 12.]])?;
+ let res = core::mul_mat_mat(&mat1, &mat2)?.to_mat()?;
+ assert_eq!(res.typ()?, f32::typ());
+ assert_eq!(res.size()?, Size::new(2, 2));
+ assert_eq!(res.data_typed::<f32>()?, &[58., 64., 139., 154.]);
+ }
+ {
+ let mat = Mat::from_slice(&[1u8, 2, 3, 4, 5, 6])?;
+ let res = core::div_mat_f64(&mat, 2.)?.to_mat()?;
+ assert_eq!(res.typ()?, u8::typ());
+ assert_eq!(res.data_typed::<u8>()?, &[0, 1, 2, 2, 2, 3]);
+ }
+ Ok(())
+}

Add support for generation of operator* (as mul and as deref)

Fixes #107