cobia/
cape_object_impl.rs1use crate::C;
2use crate::*;
3
4pub struct CapeObjectData {
14 interface: C::ICapeInterface,
16 last_error: Option<COBIAError>,
18 last_error_scope: Option<String>,
20 ref_count: i32,
22 interface_map: std::collections::HashMap<CapeUUID, *mut C::ICapeInterface>,
24}
25
26pub trait ICapeInterfaceImpl: std::fmt::Display {
32 type T: ICapeInterfaceImpl;
33
34 fn get_object_data(&mut self) -> &mut CapeObjectData;
36 fn get_self(&mut self) -> *mut Self::T;
38
39 const CAPEINTERFACE_VTABLE: C::ICapeInterface_VTable = C::ICapeInterface_VTable {
41 addReference: Some(Self::raw_add_reference),
42 release: Some(Self::raw_release),
43 queryInterface: Some(Self::raw_query_interface),
44 getLastError: Some(Self::raw_get_last_error),
45 };
46
47 fn init(&mut self) -> *mut C::ICapeInterface {
49 self.get_object_data().interface.me =
51 self.get_self() as *const Self::T as *mut std::ffi::c_void;
52 let icapeinterface = self.as_icapeinterface();
54 self.add_interface(
55 std::ptr::addr_of!(C::ICapeInterface_UUID),
56 icapeinterface,
57 );
58 self.as_icapeinterface()
59 }
60
61 fn create_object_data<Timpl: ICapeInterfaceImpl>() -> CapeObjectData {
63 CapeObjectData {
64 interface: C::ICapeInterface {
65 me: std::ptr::null_mut(),
66 vTbl: (&Timpl::CAPEINTERFACE_VTABLE as *const C::ICapeInterface_VTable).cast_mut(),
67 },
68 last_error: None,
69 last_error_scope: None,
70 ref_count: 0,
71 interface_map: std::collections::HashMap::new(),
72 }
73 }
74
75 extern "C" fn raw_add_reference(me: *mut ::std::os::raw::c_void) {
76 let p = me as *mut Self::T;
77 assert!(unsafe { &mut *p }.get_object_data().ref_count >= 0);
78 unsafe { &mut *p }.get_object_data().ref_count += 1;
79 }
80
81 extern "C" fn raw_release(me: *mut ::std::os::raw::c_void) {
82 let p = me as *mut Self::T;
83 let ref_count: &mut i32 = &mut unsafe { (*p).get_object_data() }.ref_count;
84 *ref_count -= 1;
85 if *ref_count == 0 {
86 drop(unsafe { Box::from_raw(me as *mut Self::T) });
87 }
88 }
89
90 extern "C" fn raw_query_interface(
91 me: *mut ::std::os::raw::c_void,
92 uuid: *const C::CapeUUID,
93 interface: *mut *mut C::ICapeInterface,
94 ) -> C::CapeResult {
95 let p = me as *mut Self::T;
96 let object_data: &mut CapeObjectData = unsafe { (*p).get_object_data() };
97 match object_data.interface_map.get(&(unsafe { *uuid }).clone()) {
98 Some(ptr) => {
99 unsafe { *interface = *ptr };
100 assert!(object_data.ref_count >= 0);
101 object_data.ref_count += 1;
102 COBIAERR_NOERROR
103 }
104 None => COBIAERR_NOSUCHINTERFACE,
105 }
106 }
107
108 extern "C" fn raw_get_last_error(
109 me: *mut ::std::os::raw::c_void,
110 error: *mut *mut C::ICapeError,
111 ) -> C::CapeResult {
112 if error == std::ptr::null_mut() {
113 return COBIAERR_NULLPOINTER;
114 }
115 let p = me as *mut Self::T;
116 let object_data: &mut CapeObjectData = unsafe { (*p).get_object_data() };
117 let e = match &object_data.last_error {
118 Some(e) => &e,
119 None => &COBIAError::Code(COBIAERR_NOERROR),
120 };
121 let scope = match &object_data.last_error_scope {
122 Some(s) => &s,
123 None => "<unknown>",
124 };
125 unsafe {
126 *error = CapeErrorImpl::new(e, scope, &format!("{}",*p)) as *mut C::ICapeError
127 };
128 COBIAERR_NOERROR
129 }
130
131 fn add_interface(&mut self, uuid: *const C::CapeUUID, interface: *mut C::ICapeInterface) {
138 self.get_object_data().interface_map.insert((unsafe { *uuid }).clone(),interface);
139 }
140
141 fn set_last_error(&mut self, error: COBIAError, scope: &str) -> C::CapeResult {
148 let object_data = self.get_object_data();
149 object_data.last_error_scope = Some(scope.to_string());
150 let ret_code = match error {
151 COBIAError::Code(c) => c,
152 _ => COBIAERR_CAPEOPENERROR,
153 };
154 object_data.last_error = Some(error);
155 ret_code
156 }
157
158 fn clear_last_error(&mut self) {
161 let obj = &mut self.get_object_data();
162 obj.last_error_scope = None;
163 obj.last_error = None;
164 }
165
166 fn as_icapeinterface(&mut self) -> *mut C::ICapeInterface {
169 &mut self.get_object_data().interface as *mut C::ICapeInterface
170 }
171}
172