linsight_plugin_sdk/
export.rs1#[macro_export]
30macro_rules! export_plugin {
31 ($ty:ty) => {
32 #[unsafe(no_mangle)]
33 pub extern "C" fn linsight_plugin_abi_version() -> u32 {
34 $crate::LINSIGHT_PLUGIN_ABI_VERSION
35 }
36
37 #[$crate::stabby::export]
38 pub extern "C" fn linsight_plugin_v6() -> $crate::stabby::dynptr!(
39 $crate::stabby::boxed::Box<dyn $crate::LinsightPlugin + Send + Sync>
40 ) {
41 let boxed: $crate::stabby::boxed::Box<$ty> =
42 $crate::stabby::boxed::Box::new(<$ty as Default>::default());
43 boxed.into()
44 }
45 };
46 (
47 $ty:ty,
48 metadata: {
49 plugin_id: $plugin_id:expr,
50 display_name: $display_name:expr,
51 version: $version:expr $(,)?
52 } $(,)?
53 ) => {
54 #[unsafe(no_mangle)]
55 pub extern "C" fn linsight_plugin_abi_version() -> u32 {
56 $crate::LINSIGHT_PLUGIN_ABI_VERSION
57 }
58
59 #[$crate::stabby::export]
60 pub extern "C" fn linsight_plugin_metadata_v1() -> $crate::RPluginMetadata {
61 $crate::PluginMetadata {
62 plugin_id: $plugin_id.into(),
63 display_name: $display_name.into(),
64 version: $version.into(),
65 }
66 .into()
67 }
68
69 #[$crate::stabby::export]
70 pub extern "C" fn linsight_plugin_v6() -> $crate::stabby::dynptr!(
71 $crate::stabby::boxed::Box<dyn $crate::LinsightPlugin + Send + Sync>
72 ) {
73 let boxed: $crate::stabby::boxed::Box<$ty> =
74 $crate::stabby::boxed::Box::new(<$ty as Default>::default());
75 boxed.into()
76 }
77 };
78}
79
80#[cfg(test)]
81mod tests {
82 use linsight_core::SensorId;
83 use stabby::result::Result as SResult;
84
85 use crate::{
86 LinsightPlugin, PluginCtx, PluginError, PluginManifest, RInitResult, RPluginCtx,
87 RPluginError, RPluginManifest, RReading, RSampleResult, RSensorId, host_init, host_sample,
88 };
89
90 #[derive(Default)]
91 struct EchoPlugin;
92
93 impl LinsightPlugin for EchoPlugin {
94 extern "C-unwind" fn init(&self, _ctx: &RPluginCtx) -> RInitResult {
95 let m = PluginManifest {
96 plugin_id: "echo".into(),
97 display_name: "Echo".into(),
98 version: "0.0.1".into(),
99 sensors: vec![],
100 devices: vec![],
101 };
102 let r: RPluginManifest = m.into();
103 SResult::Ok(r)
104 }
105
106 extern "C-unwind" fn sample(&self, _: RSensorId) -> RSampleResult {
107 let r: RReading = linsight_core::Reading::Scalar(1.0).into();
108 SResult::Ok(r)
109 }
110 }
111
112 #[test]
120 fn host_init_round_trips() {
121 let p = EchoPlugin;
122 let m = host_init(&p, &PluginCtx::default()).unwrap();
123 assert_eq!(m.plugin_id, "echo");
124 }
125
126 #[test]
127 fn host_sample_round_trips() {
128 let p = EchoPlugin;
129 let r = host_sample(&p, &SensorId::new("anything")).unwrap();
130 assert!(matches!(r, linsight_core::Reading::Scalar(v) if v == 1.0));
131 let _ = std::any::TypeId::of::<PluginError>();
133 let _ = std::any::TypeId::of::<RPluginError>();
134 }
135}