This is an automated email from the ASF dual-hosted git repository. pnoltes pushed a commit to branch feature/599-provide-and-use-c-service-in-rust in repository https://gitbox.apache.org/repos/asf/celix.git
commit 99717a68faaea5ec853018e5992cbc1d2f9397d5 Author: Pepijn Noltes <pepijnnol...@gmail.com> AuthorDate: Wed Aug 23 15:18:21 2023 +0200 Add registration of rust trait --- misc/experimental/rust/Cargo.toml | 1 + .../rust/celix/src/bundle_activator.rs | 10 +- misc/experimental/rust/celix/src/bundle_context.rs | 128 +++++++++++---------- misc/experimental/rust/celix/src/errno.rs | 1 - misc/experimental/rust/celix/src/lib.rs | 18 +-- misc/experimental/rust/celix/src/log_helper.rs | 31 +++-- misc/experimental/rust/celix/src/log_level.rs | 12 +- misc/experimental/rust/celix_bindings/src/lib.rs | 9 +- .../rust/hello_world_activator/src/lib.rs | 4 +- .../Cargo.toml | 7 +- .../{celix_bindings => rust_shell_api}/src/lib.rs | 13 ++- .../rust/shell_command_bundle/Cargo.toml | 1 + .../rust/shell_command_bundle/src/lib.rs | 52 +++++---- 13 files changed, 163 insertions(+), 124 deletions(-) diff --git a/misc/experimental/rust/Cargo.toml b/misc/experimental/rust/Cargo.toml index 95f253d0..9dc3d514 100644 --- a/misc/experimental/rust/Cargo.toml +++ b/misc/experimental/rust/Cargo.toml @@ -20,6 +20,7 @@ members = [ "celix_bindings", "celix", "hello_world_activator", + "rust_shell_api", "shell_command_bundle", #"rust_shell_tui", ] diff --git a/misc/experimental/rust/celix/src/bundle_activator.rs b/misc/experimental/rust/celix/src/bundle_activator.rs index 11fa22a3..a54ad5ea 100644 --- a/misc/experimental/rust/celix/src/bundle_activator.rs +++ b/misc/experimental/rust/celix/src/bundle_activator.rs @@ -24,8 +24,14 @@ use super::Error; pub trait BundleActivator { fn new(ctx: Arc<dyn BundleContext>) -> Self; - fn start(&mut self) -> Result<(), Error> { /* Default implementation */ Ok(())} - fn stop(&mut self) -> Result<(), Error> { /* Default implementation */ Ok(())} + fn start(&mut self) -> Result<(), Error> { + /* Default implementation */ + Ok(()) + } + fn stop(&mut self) -> Result<(), Error> { + /* Default implementation */ + Ok(()) + } } #[macro_export] diff --git a/misc/experimental/rust/celix/src/bundle_context.rs b/misc/experimental/rust/celix/src/bundle_context.rs index 5d2841d8..88fc4ed6 100644 --- a/misc/experimental/rust/celix/src/bundle_context.rs +++ b/misc/experimental/rust/celix/src/bundle_context.rs @@ -17,21 +17,22 @@ * under the License. */ -use std::ptr::null_mut; -use std::ffi::c_void; -use std::collections::HashMap; -use std::sync::Arc; -use std::sync::Weak; use std::any::type_name; use std::any::Any; +use std::collections::HashMap; +use std::ffi::c_void; +use std::ops::DerefMut; +use std::ptr::null_mut; +use std::sync::Arc; use std::sync::Mutex; +use std::sync::Weak; -use celix_bindings::celix_bundle_context_t; use celix_bindings::celix_bundleContext_log; -use celix_bindings::celix_properties_create; -use celix_bindings::celix_properties_set; use celix_bindings::celix_bundleContext_registerServiceWithOptions; use celix_bindings::celix_bundleContext_unregisterService; +use celix_bindings::celix_bundle_context_t; +use celix_bindings::celix_properties_create; +use celix_bindings::celix_properties_set; use celix_bindings::celix_service_registration_options_t; use super::Error; @@ -41,7 +42,6 @@ pub struct ServiceRegistration { service_id: i64, weak_ctx: Weak<BundleContextImpl>, _boxed_svc: Option<Box<dyn Any>>, - // arc_svc: Option<Arc<dyn Any>>, } impl Drop for ServiceRegistration { @@ -57,7 +57,6 @@ impl Drop for ServiceRegistration { pub struct ServiceRegistrationBuilder<'a> { ctx: &'a BundleContextImpl, boxed_svc: Option<Box<dyn Any>>, - // _arc_svc: Option<Arc<dyn Any>>, unmanaged_svc: *mut c_void, service_name: String, service_version: String, @@ -65,11 +64,10 @@ pub struct ServiceRegistrationBuilder<'a> { } impl ServiceRegistrationBuilder<'_> { - fn new<'a>(ctx: &'a BundleContextImpl) -> ServiceRegistrationBuilder<'a> { + fn new(ctx: &BundleContextImpl) -> ServiceRegistrationBuilder { ServiceRegistrationBuilder { ctx, boxed_svc: None, - //arc_svc: None, unmanaged_svc: null_mut(), service_name: "".to_string(), service_version: "".to_string(), @@ -82,41 +80,29 @@ impl ServiceRegistrationBuilder<'_> { self } - fn with_type_name_as_service_name<I>(&mut self) -> &mut Self { + fn with_service_name_if_not_set(&mut self, name: &str) -> &mut Self { if self.service_name.is_empty() { - self.service_name = type_name::<I>().to_string(); + self.service_name = name.to_string(); } self } - pub fn with_service<I:'static>(&mut self, instance: I) -> &mut Self { - self.boxed_svc = Some(Box::new(instance)); - //self.arc_svc = None; + pub fn with_service<I: 'static>(&mut self, svc: I) -> &mut Self { + self.boxed_svc = Some(Box::new(svc)); self.unmanaged_svc = null_mut(); - self.with_type_name_as_service_name::<I>() + self.with_service_name_if_not_set(type_name::<I>()) } - //TODO check if dyn is needed (e.g. a trait object is needed) - pub fn with_boxed_service<I:'static>(&mut self, instance: Box</*dyn*/ I>) -> &mut Self { - self.boxed_svc = Some(instance); - //self.arc_svc = None; + pub fn with_boxed_service<T: ?Sized + 'static>(&mut self, svc: Box<T>) -> &mut Self { + self.boxed_svc = Some(Box::new(svc)); self.unmanaged_svc = null_mut(); - self.with_type_name_as_service_name::<I>() + self.with_service_name_if_not_set(type_name::<T>()) } - //TODO check if dyn is needed (e.g. a trait object is needed) - // pub fn with_arc_instance<I:'static>(&mut self, instance: Arc</*dyn*/ I>) -> &mut Self { - // self.boxed_svc = None; - // self.arc_svc = Some(instance); - // self.unmanaged_svc = null_mut(); - // self.with_type_name_as_service_name::<I>() - // } - - pub fn with_unmanaged_service<I>(&mut self, instance: *mut I) -> &mut Self { + pub fn with_unmanaged_service<I>(&mut self, svc: *mut I) -> &mut Self { self.boxed_svc = None; - //self.arc_svc = None; - self.unmanaged_svc = instance as *mut c_void; - self.with_type_name_as_service_name::<I>() + self.unmanaged_svc = svc as *mut c_void; + self.with_service_name_if_not_set(type_name::<I>()) } pub fn with_version(&mut self, version: &str) -> &mut Self { @@ -130,18 +116,21 @@ impl ServiceRegistrationBuilder<'_> { } pub fn with_property(&mut self, key: &str, value: &str) -> &mut Self { - self.service_properties.insert(key.to_string(), value.to_string()); + self.service_properties + .insert(key.to_string(), value.to_string()); self } fn validate(&self) -> Result<(), Error> { let mut valid = true; if self.service_name.is_empty() { - self.ctx.log_error("Cannot register service. Service name is empty"); + self.ctx + .log_error("Cannot register service. Service name is empty"); valid = false; } if self.boxed_svc.is_none() && /*self.arc_svc.is_none() &&*/ self.unmanaged_svc.is_null() { - self.ctx.log_error("Cannot register service. No instance provided"); + self.ctx + .log_error("Cannot register service. No instance provided"); valid = false; } match valid { @@ -155,47 +144,45 @@ impl ServiceRegistrationBuilder<'_> { let any_svc: &mut dyn Any = boxed_svc.as_mut(); let boxed_svc_ptr = any_svc as *mut dyn Any; //note box still owns the instance boxed_svc_ptr as *mut c_void - // } else if let Some(arc_svc) = self.arc_svc.as_mut() { - // let any_svc: &mut dyn Any = arc_svc.as_mut(); - // let arc_svc_ptr = arc_svc as *mut dyn Any; //note arc still owns the instance - // arc_svc_ptr as *mut c_void } else if self.unmanaged_svc.is_null() { panic!("Cannot get c_svc. No instance provided"); } else { - self.unmanaged_svc as *mut c_void + self.unmanaged_svc } } - unsafe fn build_unsafe(&mut self) -> Result<ServiceRegistration, Error> { + unsafe fn build_unsafe(&mut self, svc_ptr: *mut c_void) -> Result<ServiceRegistration, Error> { let c_service_name = std::ffi::CString::new(self.service_name.as_str()).unwrap(); let c_service_version = std::ffi::CString::new(self.service_version.as_str()).unwrap(); let c_service_properties = celix_properties_create(); - let c_service = self.get_c_svc(); for (key, value) in self.service_properties.iter() { let c_key = std::ffi::CString::new(key.as_str()).unwrap(); let c_value = std::ffi::CString::new(value.as_str()).unwrap(); celix_properties_set(c_service_properties, c_key.as_ptr(), c_value.as_ptr()); } let opts = celix_service_registration_options_t { - svc: c_service, + svc: svc_ptr, factory: null_mut(), serviceName: c_service_name.as_ptr() as *const i8, properties: c_service_properties, serviceLanguage: null_mut(), - serviceVersion: if self.service_version.is_empty() { null_mut() } else { c_service_version.as_ptr() as *const i8}, + serviceVersion: if self.service_version.is_empty() { + null_mut() + } else { + c_service_version.as_ptr() as *const i8 + }, asyncData: null_mut(), asyncCallback: None, }; - let service_id: i64 = celix_bundleContext_registerServiceWithOptions( - self.ctx.get_c_bundle_context(), - &opts); + let service_id: i64 = + celix_bundleContext_registerServiceWithOptions(self.ctx.get_c_bundle_context(), &opts); if service_id >= 0 { Ok(ServiceRegistration { service_id, weak_ctx: self.ctx.get_self().clone(), _boxed_svc: self.boxed_svc.take(), //to ensure that a possible box instance is not dropped - // arc_svc: self.arc_svc.take(), //to ensure that a possible arc instance is not dropped + // arc_svc: self.arc_svc.take(), //to ensure that a possible arc instance is not dropped }) } else { Err(Error::BundleException) @@ -204,9 +191,10 @@ impl ServiceRegistrationBuilder<'_> { pub fn build(&mut self) -> Result<ServiceRegistration, Error> { self.validate()?; + let svc_ptr = self.get_c_svc(); unsafe { //TODO make unsafe part smaller (if possible) - self.build_unsafe() + self.build_unsafe(svc_ptr) } } } @@ -233,7 +221,7 @@ pub trait BundleContext { struct BundleContextImpl { c_bundle_context: *mut celix_bundle_context_t, - weak_self : Mutex<Option<Weak<BundleContextImpl>>>, + weak_self: Mutex<Option<Weak<BundleContextImpl>>>, } impl BundleContextImpl { @@ -267,7 +255,11 @@ impl BundleContextImpl { let result = std::ffi::CString::new(message); match result { Ok(c_str) => { - celix_bundleContext_log(self.c_bundle_context, level.into(), c_str.as_ptr() as *const i8); + celix_bundleContext_log( + self.c_bundle_context, + level.into(), + c_str.as_ptr() as *const i8, + ); } Err(e) => { println!("Error creating CString: {}", e); @@ -282,19 +274,33 @@ impl BundleContext for BundleContextImpl { self.c_bundle_context } - fn log(&self, level: LogLevel, message: &str) { self.log_to_c(level, message); } + fn log(&self, level: LogLevel, message: &str) { + self.log_to_c(level, message); + } - fn log_trace(&self, message: &str) { self.log(LogLevel::Trace, message); } + fn log_trace(&self, message: &str) { + self.log(LogLevel::Trace, message); + } - fn log_debug(&self, message: &str) { self.log(LogLevel::Debug, message); } + fn log_debug(&self, message: &str) { + self.log(LogLevel::Debug, message); + } - fn log_info(&self, message: &str) { self.log(LogLevel::Info, message); } + fn log_info(&self, message: &str) { + self.log(LogLevel::Info, message); + } - fn log_warning(&self, message: &str) { self.log(LogLevel::Warning, message); } + fn log_warning(&self, message: &str) { + self.log(LogLevel::Warning, message); + } - fn log_error(&self, message: &str){ self.log(LogLevel::Error, message); } + fn log_error(&self, message: &str) { + self.log(LogLevel::Error, message); + } - fn log_fatal(&self, message: &str){ self.log(LogLevel::Fatal, message); } + fn log_fatal(&self, message: &str) { + self.log(LogLevel::Fatal, message); + } fn register_service(&self) -> ServiceRegistrationBuilder { ServiceRegistrationBuilder::new(self) diff --git a/misc/experimental/rust/celix/src/errno.rs b/misc/experimental/rust/celix/src/errno.rs index a8037866..af23d2ca 100644 --- a/misc/experimental/rust/celix/src/errno.rs +++ b/misc/experimental/rust/celix/src/errno.rs @@ -25,7 +25,6 @@ pub const CELIX_SUCCESS: celix_status_t = celix_bindings::CELIX_SUCCESS as celix //these are defined with literal values. pub const BUNDLE_EXCEPTION: celix_status_t = 70001; - pub enum Error { BundleException, CelixStatusError(celix_status_t), // Represent not explicitly mapped celix_status_t values diff --git a/misc/experimental/rust/celix/src/lib.rs b/misc/experimental/rust/celix/src/lib.rs index b5d5dc57..b30f995e 100644 --- a/misc/experimental/rust/celix/src/lib.rs +++ b/misc/experimental/rust/celix/src/lib.rs @@ -25,29 +25,29 @@ extern crate celix_bindings; // C API in its public API. #[doc(hidden)] pub mod details { - pub use celix_bindings::celix_status_t as CStatus; pub use celix_bindings::celix_bundle_context_t as CBundleContext; + pub use celix_bindings::celix_status_t as CStatus; } mod errno; // Re-export errno types in the public API. -pub use self::errno::CELIX_SUCCESS as CELIX_SUCCESS; -pub use self::errno::Error as Error; +pub use self::errno::Error; +pub use self::errno::CELIX_SUCCESS; mod log_level; // Re-export log level types in the public API. -pub use self::log_level::LogLevel as LogLevel; +pub use self::log_level::LogLevel; mod bundle_context; // Re-export bundle context types in the public API. -pub use self::bundle_context::BundleContext as BundleContext; -pub use self::bundle_context::ServiceRegistration as ServiceRegistration; -pub use self::bundle_context::bundle_context_new as bundle_context_new; +pub use self::bundle_context::bundle_context_new; +pub use self::bundle_context::BundleContext; +pub use self::bundle_context::ServiceRegistration; mod bundle_activator; // Re-export bundle activator types in the public API. -pub use self::bundle_activator::BundleActivator as BundleActivator; +pub use self::bundle_activator::BundleActivator; mod log_helper; // Re-export log helper types in the public API. -pub use self::log_helper::LogHelper as LogHelper; +pub use self::log_helper::LogHelper; diff --git a/misc/experimental/rust/celix/src/log_helper.rs b/misc/experimental/rust/celix/src/log_helper.rs index 2af5656c..5c681024 100644 --- a/misc/experimental/rust/celix/src/log_helper.rs +++ b/misc/experimental/rust/celix/src/log_helper.rs @@ -19,13 +19,13 @@ use std::sync::Arc; -use super::LogLevel; use super::BundleContext; +use super::LogLevel; -use celix_bindings::celix_log_helper_t; use celix_bindings::celix_logHelper_create; use celix_bindings::celix_logHelper_destroy; use celix_bindings::celix_logHelper_log; +use celix_bindings::celix_log_helper_t; pub struct LogHelper { celix_log_helper: *mut celix_log_helper_t, } @@ -35,16 +35,23 @@ impl LogHelper { unsafe { let result = std::ffi::CString::new(name); match result { - Ok(c_str) => { - LogHelper { - celix_log_helper: celix_logHelper_create(ctx.get_c_bundle_context(), c_str.as_ptr() as *const i8), - } - } + Ok(c_str) => LogHelper { + celix_log_helper: celix_logHelper_create( + ctx.get_c_bundle_context(), + c_str.as_ptr() as *const i8, + ), + }, Err(e) => { - ctx.log_error(&format!("Error creating CString: {}. Using \"error\" as log name", e)); + ctx.log_error(&format!( + "Error creating CString: {}. Using \"error\" as log name", + e + )); let c_str = std::ffi::CString::new("error").unwrap(); LogHelper { - celix_log_helper: celix_logHelper_create(ctx.get_c_bundle_context(), c_str.as_ptr() as *const i8), + celix_log_helper: celix_logHelper_create( + ctx.get_c_bundle_context(), + c_str.as_ptr() as *const i8, + ), } } } @@ -56,7 +63,11 @@ impl LogHelper { let result = std::ffi::CString::new(message); match result { Ok(c_str) => { - celix_logHelper_log(self.celix_log_helper, level.into(), c_str.as_ptr() as *const i8); + celix_logHelper_log( + self.celix_log_helper, + level.into(), + c_str.as_ptr() as *const i8, + ); } Err(e) => { println!("Error creating CString: {}", e); diff --git a/misc/experimental/rust/celix/src/log_level.rs b/misc/experimental/rust/celix/src/log_level.rs index bc9b5e48..5beab988 100644 --- a/misc/experimental/rust/celix/src/log_level.rs +++ b/misc/experimental/rust/celix/src/log_level.rs @@ -17,14 +17,14 @@ * under the License. */ -use celix_bindings::celix_log_level_e; -use celix_bindings::celix_log_level_CELIX_LOG_LEVEL_TRACE as CELIX_LOG_LEVEL_TRACE; use celix_bindings::celix_log_level_CELIX_LOG_LEVEL_DEBUG as CELIX_LOG_LEVEL_DEBUG; -use celix_bindings::celix_log_level_CELIX_LOG_LEVEL_INFO as CELIX_LOG_LEVEL_INFO; -use celix_bindings::celix_log_level_CELIX_LOG_LEVEL_WARNING as CELIX_LOG_LEVEL_WARNING; +use celix_bindings::celix_log_level_CELIX_LOG_LEVEL_DISABLED as CELIX_LOG_LEVEL_DISABLED; use celix_bindings::celix_log_level_CELIX_LOG_LEVEL_ERROR as CELIX_LOG_LEVEL_ERROR; use celix_bindings::celix_log_level_CELIX_LOG_LEVEL_FATAL as CELIX_LOG_LEVEL_FATAL; -use celix_bindings::celix_log_level_CELIX_LOG_LEVEL_DISABLED as CELIX_LOG_LEVEL_DISABLED; +use celix_bindings::celix_log_level_CELIX_LOG_LEVEL_INFO as CELIX_LOG_LEVEL_INFO; +use celix_bindings::celix_log_level_CELIX_LOG_LEVEL_TRACE as CELIX_LOG_LEVEL_TRACE; +use celix_bindings::celix_log_level_CELIX_LOG_LEVEL_WARNING as CELIX_LOG_LEVEL_WARNING; +use celix_bindings::celix_log_level_e; pub enum LogLevel { Trace, @@ -33,7 +33,7 @@ pub enum LogLevel { Warning, Error, Fatal, - Disabled + Disabled, } impl From<celix_log_level_e> for LogLevel { fn from(level: celix_log_level_e) -> Self { diff --git a/misc/experimental/rust/celix_bindings/src/lib.rs b/misc/experimental/rust/celix_bindings/src/lib.rs index 64fdba67..0fd4dc70 100644 --- a/misc/experimental/rust/celix_bindings/src/lib.rs +++ b/misc/experimental/rust/celix_bindings/src/lib.rs @@ -17,8 +17,13 @@ * under the License. */ -#[allow(non_camel_case_types, non_snake_case, non_upper_case_globals, dead_code)] +#[allow( + non_camel_case_types, + non_snake_case, + non_upper_case_globals, + dead_code +)] mod bindings { - include!(concat!(env!("OUT_DIR"), "/celix_bindings.rs")); + include!(concat!(env!("OUT_DIR"), "/celix_bindings.rs")); } pub use bindings::*; diff --git a/misc/experimental/rust/hello_world_activator/src/lib.rs b/misc/experimental/rust/hello_world_activator/src/lib.rs index 93c676ef..c9e6e861 100644 --- a/misc/experimental/rust/hello_world_activator/src/lib.rs +++ b/misc/experimental/rust/hello_world_activator/src/lib.rs @@ -32,9 +32,7 @@ struct HelloWorldBundle { impl BundleActivator for HelloWorldBundle { fn new(ctx: Arc<dyn celix::BundleContext>) -> Self { ctx.log_info("Hello World Bundle Activator created"); - HelloWorldBundle{ - ctx, - } + HelloWorldBundle { ctx } } fn start(&mut self) -> Result<(), Error> { diff --git a/misc/experimental/rust/shell_command_bundle/Cargo.toml b/misc/experimental/rust/rust_shell_api/Cargo.toml similarity index 85% copy from misc/experimental/rust/shell_command_bundle/Cargo.toml copy to misc/experimental/rust/rust_shell_api/Cargo.toml index 1773c986..71c4d41b 100644 --- a/misc/experimental/rust/shell_command_bundle/Cargo.toml +++ b/misc/experimental/rust/rust_shell_api/Cargo.toml @@ -16,14 +16,13 @@ # under the License. [package] -name = "rust_shell_command_activator" +name = "rust_shell_api" version = "0.0.1" [dependencies] -celix_bindings = { path = "../celix_bindings" } celix = { path = "../celix" } [lib] -name = "rust_shell_command_activator" +name = "rust_shell_api" path = "src/lib.rs" -crate-type = ["cdylib"] +crate-type = ["rlib"] diff --git a/misc/experimental/rust/celix_bindings/src/lib.rs b/misc/experimental/rust/rust_shell_api/src/lib.rs similarity index 72% copy from misc/experimental/rust/celix_bindings/src/lib.rs copy to misc/experimental/rust/rust_shell_api/src/lib.rs index 64fdba67..79a11de2 100644 --- a/misc/experimental/rust/celix_bindings/src/lib.rs +++ b/misc/experimental/rust/rust_shell_api/src/lib.rs @@ -17,8 +17,13 @@ * under the License. */ -#[allow(non_camel_case_types, non_snake_case, non_upper_case_globals, dead_code)] -mod bindings { - include!(concat!(env!("OUT_DIR"), "/celix_bindings.rs")); +extern crate celix; + +use celix::Error; +pub const COMMAND_NAME: &str = "command.name"; +pub const COMMAND_USAGE: &str = "command.usage"; +pub const COMMAND_DESCRIPTION: &str = "command.description"; + +pub trait RustShellCommand { + fn execute_command(&mut self, command_line: &str) -> Result<(), Error>; } -pub use bindings::*; diff --git a/misc/experimental/rust/shell_command_bundle/Cargo.toml b/misc/experimental/rust/shell_command_bundle/Cargo.toml index 1773c986..0c11c180 100644 --- a/misc/experimental/rust/shell_command_bundle/Cargo.toml +++ b/misc/experimental/rust/shell_command_bundle/Cargo.toml @@ -22,6 +22,7 @@ version = "0.0.1" [dependencies] celix_bindings = { path = "../celix_bindings" } celix = { path = "../celix" } +rust_shell_api = { path = "../rust_shell_api" } [lib] name = "rust_shell_command_activator" diff --git a/misc/experimental/rust/shell_command_bundle/src/lib.rs b/misc/experimental/rust/shell_command_bundle/src/lib.rs index 1ed3b04d..0ab73f78 100644 --- a/misc/experimental/rust/shell_command_bundle/src/lib.rs +++ b/misc/experimental/rust/shell_command_bundle/src/lib.rs @@ -17,21 +17,22 @@ * under the License. */ -extern crate celix_bindings; extern crate celix; +extern crate celix_bindings; +extern crate rust_shell_api; -use std::sync::Arc; -use std::ffi::c_void; use std::ffi::c_char; +use std::ffi::c_void; +use std::sync::{Arc, Mutex}; use celix::BundleActivator; use celix::BundleContext; use celix::Error; +use rust_shell_api::RustShellCommand; use celix_bindings::celix_shell_command_t; use celix_bindings::FILE; - struct CShellCommandImpl { ctx: Arc<dyn BundleContext>, } @@ -39,12 +40,15 @@ struct CShellCommandImpl { impl CShellCommandImpl { fn new(ctx: Arc<dyn BundleContext>) -> Self { ctx.log_info("Shell Command created"); - CShellCommandImpl { - ctx, - } + CShellCommandImpl { ctx } } - extern "C" fn call_execute_command(handle: *mut c_void, command_line: *const c_char, _out_stream: *mut FILE, _error_stream: *mut FILE) -> bool { + extern "C" fn call_execute_command( + handle: *mut c_void, + command_line: *const c_char, + _out_stream: *mut FILE, + _error_stream: *mut FILE, + ) -> bool { if handle.is_null() || command_line.is_null() { return false; } @@ -58,14 +62,12 @@ impl CShellCommandImpl { } fn execute_command(&mut self, command_line: &str) { - self.ctx.log_info(format!("Execute command: {}", command_line).as_str()); + self.ctx + .log_info(format!("Execute command: {}", command_line).as_str()); } } //temporary, should be moved in a separate API crate -trait RustShellCommand { - fn execute_command(&mut self, command_line: &str) -> Result<(), Error>; -} struct RustShellCommandImpl { ctx: Arc<dyn BundleContext>, @@ -74,15 +76,14 @@ struct RustShellCommandImpl { impl RustShellCommandImpl { fn new(ctx: Arc<dyn BundleContext>) -> Self { ctx.log_info("Rust Shell Command created"); - RustShellCommandImpl { - ctx, - } + RustShellCommandImpl { ctx } } } impl RustShellCommand for RustShellCommandImpl { fn execute_command(&mut self, command_line: &str) -> Result<(), Error> { - self.ctx.log_info(format!("Execute command: {}.", command_line).as_str()); + self.ctx + .log_info(format!("Execute command: {}.", command_line).as_str()); Ok(()) } } @@ -93,6 +94,7 @@ struct ShellCommandActivator { shell_command_provider: CShellCommandImpl, c_registration: Option<celix::ServiceRegistration>, rust_registration: Option<celix::ServiceRegistration>, + rust_registration2: Option<celix::ServiceRegistration>, } impl BundleActivator for ShellCommandActivator { @@ -103,28 +105,33 @@ impl BundleActivator for ShellCommandActivator { //log_helper: log_helper_new(&*ctx, "ShellCommandBundle"), c_registration: None, rust_registration: None, + rust_registration2: None, }; result } fn start(&mut self) -> Result<(), Error> { + + //C service registered as direct type let registration = self.ctx.register_service() - .with_service( celix_shell_command_t{ + .with_service(celix_shell_command_t { handle: &mut self.shell_command_provider as *mut CShellCommandImpl as *mut c_void, executeCommand: Some(CShellCommandImpl::call_execute_command), - }) + }) .with_service_name("celix_shell_command") - .with_property("command.name", "exe_in_rust") + .with_property("command.name", "exe_c_command_in_rust") .with_property("command.description", "Simple command written in Rust") .build()?; self.c_registration = Some(registration); self.ctx.log_info("C Shell Command registered"); + //Rust service register using a Box with a trait let rust_shell_command = Box::new(RustShellCommandImpl::new(self.ctx.clone())); + let rust_shell_command = Box::<dyn RustShellCommand>::from(rust_shell_command); let registration = self.ctx.register_service() //maybe make svc types more explicit, e.g.with type parameters - .with_service(rust_shell_command as Box<dyn RustShellCommand>) - .with_property("command.name", "exe_in_rust") - .with_property("command.description", "Simple command written in Rust") + .with_boxed_service(rust_shell_command) + .with_property(rust_shell_api::COMMAND_NAME, "exe_rust_command") + .with_property(rust_shell_api::COMMAND_DESCRIPTION, "Simple command written in Rust") .build()?; self.rust_registration = Some(registration); @@ -133,6 +140,7 @@ impl BundleActivator for ShellCommandActivator { } fn stop(&mut self) -> Result<(), Error> { + self.rust_registration2 = None; self.rust_registration = None; self.c_registration = None; self.ctx.log_info("Rust Shell Command stopped");