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");

Reply via email to