Add special handling for cases where C++ char type corresponds to Rust char type
MODIFY
binding-generator/src/settings.rs
binding-generator/src/settings.rs
@@ -912,6 +912,8 @@ pub enum ArgOverride {
Slice,
LenForSlice(&'static str, usize),
StringAsBytes,
+ // when C++ char needs to be represented as Rust char
+ Char8AsChar,
}
pub static ARGUMENT_OVERRIDE: Lazy<HashMap<FuncId, HashMap<&str, ArgOverride>>> = Lazy::new(|| hashmap! {
@@ -1015,6 +1017,12 @@ pub static ARGUMENT_OVERRIDE: Lazy<HashMap<FuncId, HashMap<&str, ArgOverride>>>
FuncId::new("cv::getOptimalNewCameraMatrix", ["cameraMatrix", "distCoeffs", "imageSize", "alpha", "newImgSize", "validPixROI", "centerPrincipalPoint"]) => hashmap! {
"validPixROI" => ArgOverride::Nullable,
},
+ FuncId::new("cv::VideoWriter::fourcc", ["c1", "c2", "c3", "c4"]) => hashmap! {
+ "c1" => ArgOverride::Char8AsChar,
+ "c2" => ArgOverride::Char8AsChar,
+ "c3" => ArgOverride::Char8AsChar,
+ "c4" => ArgOverride::Char8AsChar,
+ },
});
pub static NO_SKIP_NAMESPACE_IN_LOCALNAME: Lazy<HashMap<&str, HashMap<&str, &str>>> = Lazy::new(|| hashmap! {

MODIFY
binding-generator/src/type_ref.rs
binding-generator/src/type_ref.rs
@@ -36,13 +36,12 @@ use crate::{
GeneratorEnv,
IteratorExt,
ReturnTypeWrapper,
- settings,
+ settings::{self, ArgOverride},
SmartPtr,
StringExt,
Typedef,
Vector,
};
-use crate::settings::ArgOverride;
mod renderer;
@@ -66,6 +65,12 @@ pub enum StrEnc {
Binary,
}
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub enum Signedness {
+ Unsigned,
+ Signed,
+}
+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Dir<T> {
In(T),
@@ -696,6 +701,24 @@ impl<'tu, 'ge> TypeRef<'tu, 'ge> {
}
}
+ pub fn as_char8(&self) -> Option<Signedness> {
+ if matches!(self.type_hint, TypeRefTypeHint::ArgOverride(ArgOverride::Char8AsChar)) {
+ match self.type_ref.get_kind() {
+ TypeKind::CharS => {
+ Some(Signedness::Signed)
+ }
+ TypeKind::CharU => {
+ Some(Signedness::Unsigned)
+ }
+ _ => {
+ None
+ },
+ }
+ } else {
+ None
+ }
+ }
+
pub fn is_nullable(&self) -> bool {
matches!(self.type_hint, TypeRefTypeHint::ArgOverride(ArgOverride::NullableSlice) | TypeRefTypeHint::ArgOverride(ArgOverride::Nullable))
}
@@ -1073,6 +1096,8 @@ impl<'tu, 'ge> TypeRef<'tu, 'ge> {
break 'decl_type "&mut dyn core::ToInputOutputArray".into();
} else if let Some((_, size)) = self.as_string_array() {
break 'decl_type self.format_as_array("&str", size).into();
+ } else if self.as_char8().is_some() {
+ break 'decl_type "char".into();
}
break 'decl_type self.rust_full();
};
@@ -1265,6 +1290,15 @@ impl<'tu, 'ge> TypeRef<'tu, 'ge> {
arg=arg,
)
}
+ match self.as_char8() {
+ Some(Signedness::Unsigned) => {
+ return format!("u8::try_from({name})?", name=name);
+ }
+ Some(Signedness::Signed) => {
+ return format!("u8::try_from({name})? as i8", name=name);
+ }
+ None => {}
+ }
name.to_string()
}

MODIFY
src/error.rs
src/error.rs
use std::{
+ char::TryFromCharError,
ffi::NulError,
fmt,
};
@@ -32,6 +33,13 @@ impl From<NulError> for Error {
}
}
+impl From<TryFromCharError> for Error {
+ #[inline]
+ fn from(_: TryFromCharError) -> Self {
+ Self::new(core::StsBadArg, "Passed Rust char can't be converted to C++ char")
+ }
+}
+
impl std::error::Error for Error {}
pub type Result<T, E = Error> = ::std::result::Result<T, E>;

MODIFY
src/lib.rs
src/lib.rs
@@ -40,6 +40,7 @@ pub(crate) mod mod_prelude_sys {
/// Prelude for generated modules and types
pub(crate) mod mod_prelude {
+ pub use std::convert::TryFrom;
pub use crate::{
Error,
Result,

Add special handling for cases where C++ char type corresponds to Rust char type