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() };
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 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#[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#[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#[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}