cobia/cobia_pmc_helpers.rs
1use crate::*;
2
3/// PMCInfo is a struct that contains the information required to register a PMC.
4///
5/// An array of PMCInfo objects is defined by a module that implements PMCs
6/// that must be registered.
7///
8/// The above example expects my_pmc_class_1 and my_pmc_class_2
9/// to be in scope and implement the PMCRegisterationInfo traits.
10///
11/// the PMCS array is then passed to the pmc_entry_points! macro,
12/// a boolean to determine whether the PMCs are registered for all
13/// users or just the current user.
14///
15/// The pmc_entry_points! macro generates the required entry points
16/// to be used by the COBIA registration tool
17///
18/// # Example
19///
20/// See the example in the lib.rs file in the pmc module
21
22pub struct PMCInfo {
23 pub create_instance: fn(*mut *mut C::ICapeInterface) -> CapeResult,
24 pub registration_details: fn(&CapeRegistrar) -> Result<(), COBIAError>,
25 pub get_uuid: fn() -> CapeUUID,
26}
27
28/// PMCRegisterationInfo is a trait that must be implemented by a struct that
29/// implements a PMC. The trait provides the information required to register
30/// the PMC with the COBIA registry.
31///
32/// # Example
33///
34/// See the example in the unit_operation.rs file in the pmc module
35
36pub trait PMCRegisterationInfo {
37 fn registration_details(registrar: &CapeRegistrar) -> Result<(), COBIAError>;
38 fn get_uuid() -> CapeUUID;
39}
40
41/// CapeCreateInstance is creates an instance of a PMC object. This trait is
42/// typically implemented by the cape_object_implementation! macro
43/// and only for objects created with the cape_object_implementation! macro,
44/// which do not take any arguments for construction.
45
46pub trait CapeCreateInstance {
47 fn create_instance(instance: *mut *mut C::ICapeInterface) -> CapeResult;
48}
49
50/// class factory for a pmc_info object from a CAPE-OPEN object class
51///
52/// # Example:
53///
54/// See PMCInfo documentation
55
56pub const fn pmc_info<T: PMCRegisterationInfo + CapeCreateInstance>() -> PMCInfo {
57 PMCInfo {
58 create_instance: T::create_instance,
59 registration_details: T::registration_details,
60 get_uuid: T::get_uuid,
61 }
62}
63
64/// register a PMC into the COBIA registry
65///
66/// This entry point is called by the the capeRegisterObjects entry point
67/// that is generated from the pmc_entry_points! macro to register a PMC
68
69pub fn register_pmc(pmc_info: &PMCInfo, writer: &CapeRegistryWriter) -> Result<(), COBIAError> {
70 let registrar = writer.get_pmc_registrar()?;
71 (pmc_info.registration_details)(®istrar)?;
72 let p = match process_path::get_dylib_path() {
73 Some(p) => p,
74 None => return Err(COBIAError::Code(COBIAERR_UNKNOWNERROR)),
75 };
76 let p = match p.to_str() {
77 Some(p) => p,
78 None => return Err(COBIAError::Code(COBIAERR_UNKNOWNERROR)),
79 };
80 registrar.add_location(inproc_service_type(), p)?;
81 registrar.commit()?;
82 Ok(())
83}
84
85/// unregister a PMC from the COBIA registry
86///
87/// This entry point is called by the the capeUnregisterObjects entry point
88/// that is generated from the pmc_entry_points! macro to register a PMC
89
90pub fn unregister_pmc(pmc_info: &PMCInfo, writer: &CapeRegistryWriter) -> Result<(), COBIAError> {
91 writer.unregister_pmc_service(&(pmc_info.get_uuid)(), inproc_service_type())?;
92 Ok(())
93}
94
95/// Generate PMC entry points
96///
97/// This macro creates the PMC module entry points for PMC registration,
98/// unregistration and object creation.
99///
100/// The macro takes two arguments:
101///
102/// 1. A slice of PMCInfo objects that contain the information required to register
103/// the PMCs
104/// 2. A boolean that determines whether the PMCs are registered for all users or just the current user
105///
106/// # Example
107///
108/// See the example in the lib.rs file in the pmc module
109
110#[macro_export]
111macro_rules! pmc_entry_points {
112 ( $pmc_defs:expr, $register_for_all_users:expr ) => {
113
114 /// Type registration entry point for the module.
115 ///
116 /// This function is called by the COBIA registration tool to register the PMCs
117 /// defined in the module.
118 ///
119 /// # Returns
120 /// * A `Result` indicating success or failure of the registration.
121
122 fn register_types() -> Result<(), cobia::COBIAError> {
123 //register the cobia pmc
124 cobia::cape_open_initialize()?;
125 let writer = cobia::CapeRegistryWriter::new($register_for_all_users)?;
126 match ($pmc_defs)
127 .into_iter()
128 .try_for_each(|pmc| -> Result<(), cobia::COBIAError> {
129 cobia::register_pmc(&pmc, &writer)?;
130 Ok(())
131 }) {
132 Ok(_) => {
133 writer.commit()?;
134 Ok(())
135 }
136 Err(e) => {
137 return Err(e);
138 }
139 }
140 }
141
142 ///COBIA PMC registration entry point
143 ///
144 /// This function is called by the COBIA registration tool to register the PMCs
145 /// defined in the module.
146 ///
147 /// # Returns
148 /// * A `CapeResult` indicating success or failure of the registration.
149
150 #[unsafe(no_mangle)]
151 pub extern "C" fn capeRegisterObjects() -> cobia::CapeResult {
152 match register_types() {
153 Ok(_) => cobia::COBIAERR_NOERROR,
154 Err(e) => e.as_code(),
155 }
156 }
157
158 /// Type unregistration entry point for the module.
159 ///
160 /// This function is called by the COBIA registration tool to unregister the PMCs
161 /// defined in the module.
162 ///
163 /// # Returns
164 /// * A `Result` indicating success or failure of the unregistration.
165
166 fn unregister_types() -> Result<(), cobia::COBIAError> {
167 //unregister the cobia pmc
168 cobia::cape_open_initialize()?;
169 let writer = cobia::CapeRegistryWriter::new($register_for_all_users)?;
170 match ($pmc_defs)
171 .into_iter()
172 .try_for_each(|pmc| -> Result<(), cobia::COBIAError> {
173 cobia::unregister_pmc(&pmc, &writer)?;
174 Ok(())
175 }) {
176 Ok(_) => {
177 writer.commit()?;
178 Ok(())
179 }
180 Err(e) => {
181 return Err(e);
182 }
183 }
184 }
185
186 /// COBIA PMC unregistration entry point
187 ///
188 /// This function is called by the COBIA registration tool to unregister the PMCs
189 /// defined in the module.
190 ///
191 /// # Returns
192 /// * A `CapeResult` indicating success or failure of the unregistration.
193
194 #[unsafe(no_mangle)]
195 pub extern "C" fn capeUnregisterObjects() -> cobia::CapeResult {
196 match unregister_types() {
197 Ok(_) => cobia::COBIAERR_NOERROR,
198 Err(e) => e.as_code(),
199 }
200 }
201
202 /// COBIA PMC object creation entry point
203 ///
204 /// This function is called by the COBIA runtime to create an instance of a PMC object.
205 ///
206 /// # Arguments
207 /// * `uuid` - A pointer to the UUID of the PMC object to create.
208 /// * `ptr` - A mutable pointer to a pointer where the created object will be stored.
209 ///
210 /// # Returns
211 /// * A `CapeResult` indicating success or failure of the object creation.
212
213 #[unsafe(no_mangle)]
214 pub extern "C" fn capeCreateObject(
215 uuid: *const cobia::CapeUUID,
216 ptr: *mut *mut cobia::C::ICapeInterface,
217 ) -> cobia::CapeResult {
218 let u = unsafe { *uuid };
219 match ($pmc_defs).into_iter().find(|pmc| (pmc.get_uuid)() == u) {
220 Some(pmc) => {
221 let res = (pmc.create_instance)(ptr);
222 if res == cobia::COBIAERR_NOERROR {
223 unsafe {
224 let p = *ptr as *mut cobia::C::ICapeInterface;
225 (*(*p).vTbl).addReference.unwrap()((*p).me);
226 }
227 }
228 res
229 }
230 None => cobia::COBIAERR_NOSUCHITEM,
231 }
232 }
233 };
234}