opencv/
templ.rs

1use std::ffi::{c_char, CStr};
2use std::slice;
3
4use crate::platform_types::size_t;
5
6macro_rules! extern_container_arg {
7	(nofail mut $name: ident) => {
8		let mut $name = $name.opencv_into_extern_container_nofail();
9	};
10	(nofail $name: ident) => {
11		let $name = $name.opencv_into_extern_container_nofail();
12	};
13	(mut $name: ident) => {
14		let mut $name = $name.opencv_into_extern_container()?;
15	};
16	($name: ident) => {
17		let $name = $name.opencv_into_extern_container()?;
18	};
19}
20
21macro_rules! string_arg_output_send {
22	(via $name_via: ident) => {
23		let mut $name_via = ::std::ptr::null_mut();
24	};
25}
26
27macro_rules! string_arg_output_receive {
28	($name_via: ident => $name: ident) => {
29		*$name = unsafe { $crate::templ::receive_string($name_via.cast()) };
30	};
31}
32
33macro_rules! callback_arg {
34	($tr_name: ident($($tr_arg_name: ident: $tr_arg_type: ty),*) -> $tr_ret: ty => $tr_userdata_name: ident in $callback_name: ident($($fw_arg_name: ident: $fw_arg_type: ty),*) -> $fw_ret: ty) => {
35		unsafe extern "C" fn trampoline($($tr_arg_name: $tr_arg_type),*) -> $tr_ret {
36			let callback: *mut Box<dyn FnMut($($fw_arg_type),*) -> $fw_ret> = $tr_userdata_name.cast();
37			let out = unsafe { (*callback)($($fw_arg_name),*) };
38			out
39		}
40
41		let $tr_name = if $callback_name.is_some() {
42			Some(trampoline as unsafe extern "C" fn($($tr_arg_type),*) -> $tr_ret)
43		} else {
44			None
45		};
46	}
47}
48
49macro_rules! userdata_arg {
50	($userdata_name: ident: $userdata_type: ty => $callback_name: ident) => {
51		let $userdata_name: $userdata_type = if let Some(callback) = $callback_name {
52			Box::into_raw(Box::new(callback)).cast()
53		} else {
54			::std::ptr::null_mut() // fixme, remove previous callback
55		};
56	};
57}
58
59macro_rules! input_array_arg {
60	($name: ident) => {
61		let $name = $name.input_array()?;
62	};
63}
64
65macro_rules! output_array_arg {
66	($name: ident) => {
67		let $name = $name.output_array()?;
68	};
69}
70
71macro_rules! input_output_array_arg {
72	($name: ident) => {
73		let $name = $name.input_output_array()?;
74	};
75}
76
77macro_rules! string_array_arg {
78	($name: ident) => {
79		let $name = $name
80			.iter()
81			.map(|x| ::std::ffi::CString::new(*x).expect("invalid C string"))
82			.collect::<::std::vec::Vec<_>>();
83		let $name = $name.iter().map(|x| x.as_ptr()).collect::<::std::vec::Vec<_>>();
84	};
85}
86
87#[allow(unused_macros)]
88macro_rules! string_array_arg_mut {
89	($name: ident) => {
90		let $name = $name
91			.iter()
92			.map(|x| ::std::ffi::CString::new(*x).expect("invalid C string"))
93			.collect::<::std::vec::Vec<_>>();
94		// fixme: Casting to mut below trusts on undefined CString behavior.
95		let mut $name = $name.iter().map(|x| x.as_ptr().cast_mut()).collect::<::std::vec::Vec<_>>();
96	};
97}
98
99macro_rules! smart_ptr_option_arg {
100	(ref $name: ident) => {
101		let null = if $name.is_none() {
102			Some(unsafe { $crate::core::Ptr::new_null() })
103		} else {
104			None
105		};
106		let $name = $name.or(null.as_ref()).expect("Nullability should have been checked");
107	};
108	($name: ident) => {
109		let $name = $name.unwrap_or_else(|| unsafe { $crate::core::Ptr::new_null() });
110	};
111}
112
113macro_rules! return_send {
114	(via $name: ident) => {
115		let mut $name = ::std::mem::MaybeUninit::uninit();
116	};
117}
118
119macro_rules! return_receive {
120	($name_via: ident => $name: ident) => {
121		let $name = unsafe { $name_via.assume_init() };
122	};
123}
124
125/// The return type of this function goes into `receive_string::<String>()`
126#[inline(always)]
127pub unsafe fn ocvrs_create_string(s: *const c_char) -> *mut String {
128	let s = unsafe { CStr::from_ptr(s) }.to_string_lossy().into_owned();
129	Box::into_raw(Box::new(s))
130}
131
132/// The return type of this function goes into `receive_string::<Vec<u8>>()`
133#[inline(always)]
134pub unsafe fn ocvrs_create_byte_string(v: *const u8, len: size_t) -> *mut Vec<u8> {
135	let byte_slice = if v.is_null() {
136		&[]
137	} else {
138		unsafe { slice::from_raw_parts(v, len) }
139	};
140	let v = byte_slice.to_vec();
141	Box::into_raw(Box::new(v))
142}
143
144/// Used for both regular `String` and byte string (`Vec<u8>`)
145#[inline]
146pub unsafe fn receive_string<T>(s: *mut T) -> T {
147	if s.is_null() {
148		panic!("Got null pointer for receive_string()");
149	}
150	unsafe { *Box::from_raw(s) }
151}