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)(&registrar)?;
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}