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 3b4ccb9effd87c42e3ddb973ab7075f1e4ac03fd Author: Pepijn Noltes <pepijnnol...@gmail.com> AuthorDate: Sun Aug 20 16:43:31 2023 +0200 #599: Refactor rust api into modules --- misc/experimental/rust/CMakeLists.txt | 22 +++--- misc/experimental/rust/Cargo.toml | 2 +- .../rust/celix_bindings/src/BundleActivator.rs | 78 ------------------ .../celix_bindings/src/celix/bundle_activator.rs | 92 ++++++++++++++++++++++ .../{BundleContext.rs => celix/bundle_context.rs} | 11 ++- .../celix_bindings/src/{lib.rs => celix/errno.rs} | 43 +++++----- .../src/{LogHelper.rs => celix/log_helper.rs} | 8 +- .../celix_bindings/src/{lib.rs => celix/mod.rs} | 37 ++++----- misc/experimental/rust/celix_bindings/src/lib.rs | 22 +----- .../rust/hello_world_activator/src/lib.rs | 16 ++-- 10 files changed, 165 insertions(+), 166 deletions(-) diff --git a/misc/experimental/rust/CMakeLists.txt b/misc/experimental/rust/CMakeLists.txt index 3a710803..a98150f2 100644 --- a/misc/experimental/rust/CMakeLists.txt +++ b/misc/experimental/rust/CMakeLists.txt @@ -41,11 +41,11 @@ if (CELIX_RUST_EXPERIMENTAL) add_celix_bundle(rust_bundle ACTIVATOR ${ACTUAL_LIB_TARGET}) add_dependencies(rust_bundle rust_bundle_activator) - corrosion_add_target_local_rustflags(rust_shell_tui_activator "-Cprefer-dynamic") - corrosion_link_libraries(rust_shell_tui_activator Celix::framework) - get_target_property(ACTUAL_LIB_TARGET rust_shell_tui_activator INTERFACE_LINK_LIBRARIES) - add_celix_bundle(rust_shell_tui ACTIVATOR ${ACTUAL_LIB_TARGET}) - add_dependencies(rust_shell_tui rust_shell_tui_activator) +# corrosion_add_target_local_rustflags(rust_shell_tui_activator "-Cprefer-dynamic") +# corrosion_link_libraries(rust_shell_tui_activator Celix::framework) +# get_target_property(ACTUAL_LIB_TARGET rust_shell_tui_activator INTERFACE_LINK_LIBRARIES) +# add_celix_bundle(rust_shell_tui ACTIVATOR ${ACTUAL_LIB_TARGET}) +# add_dependencies(rust_shell_tui rust_shell_tui_activator) add_celix_container(rust_container NO_COPY BUNDLES @@ -54,11 +54,11 @@ if (CELIX_RUST_EXPERIMENTAL) rust_bundle ) - add_celix_container(rust_shell_tui_cnt NO_COPY - BUNDLES - Celix::shell - Celix::shell_tui - rust_shell_tui - ) +# add_celix_container(rust_shell_tui_cnt NO_COPY +# BUNDLES +# Celix::shell +# Celix::shell_tui +# rust_shell_tui +# ) endif() diff --git a/misc/experimental/rust/Cargo.toml b/misc/experimental/rust/Cargo.toml index ef69f6c6..891c8dd6 100644 --- a/misc/experimental/rust/Cargo.toml +++ b/misc/experimental/rust/Cargo.toml @@ -19,5 +19,5 @@ members = [ "celix_bindings", "hello_world_activator", - "rust_shell_tui", + #"rust_shell_tui", ] diff --git a/misc/experimental/rust/celix_bindings/src/BundleActivator.rs b/misc/experimental/rust/celix_bindings/src/BundleActivator.rs deleted file mode 100644 index e46ea8d3..00000000 --- a/misc/experimental/rust/celix_bindings/src/BundleActivator.rs +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -pub trait BundleActivator { - fn new(ctx: &mut dyn BundleContext) -> Self; - fn start(&mut self, ctx: &mut dyn BundleContext) -> celix_status_t { /* Default implementation */ CELIX_SUCCESS} - fn stop(&mut self, ctx: &mut dyn BundleContext) -> celix_status_t { /* Default implementation */ CELIX_SUCCESS} -} - -#[macro_export] -macro_rules! generate_bundle_activator { - ($activator:ident) => { - use celix::BundleContextImpl; - use CELIX_SUCCESS; - use celix_bindings::celix_bundle_context_t; - - struct ActivatorWrapper { - ctx: BundleContextImpl, - activator: $activator, - } - - #[no_mangle] - pub unsafe extern "C" fn celix_bundleActivator_create( - ctx: *mut celix_bundle_context_t, - out: *mut *mut c_void, - ) -> celix_status_t { - let mut context = BundleContextImpl::new(ctx); - let activator = $activator::new(&mut context); - let wrapper = ActivatorWrapper { - ctx: context, - activator - }; - *out = Box::into_raw(Box::new(wrapper)) as *mut c_void; - CELIX_SUCCESS - } - - #[no_mangle] - pub unsafe extern "C" fn celix_bundleActivator_start( - handle: *mut c_void, - ctx: *mut celix_bundle_context_t, - ) -> celix_status_t { - let wrapper = &mut *(handle as *mut ActivatorWrapper); - wrapper.activator.start(&mut wrapper.ctx) - } - - #[no_mangle] - pub unsafe extern "C" fn celix_bundleActivator_stop( - handle: *mut c_void, - ctx: *mut celix_bundle_context_t, - ) -> celix_status_t { - let wrapper = &mut *(handle as *mut ActivatorWrapper); - wrapper.activator.stop(&mut wrapper.ctx) - } - - #[no_mangle] - pub unsafe extern "C" fn celix_bundleActivator_destroy(handle: *mut c_void) -> celix_status_t { - let wrapper = Box::from_raw(handle as *mut ActivatorWrapper); - drop(wrapper); - CELIX_SUCCESS - } - }; -} diff --git a/misc/experimental/rust/celix_bindings/src/celix/bundle_activator.rs b/misc/experimental/rust/celix_bindings/src/celix/bundle_activator.rs new file mode 100644 index 00000000..01dece71 --- /dev/null +++ b/misc/experimental/rust/celix_bindings/src/celix/bundle_activator.rs @@ -0,0 +1,92 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +use ::celix::BundleContext; +use ::celix::Error; + +pub trait BundleActivator { + fn new(ctx: &mut dyn BundleContext) -> Self; + fn start(&mut self, _ctx: &mut dyn BundleContext) -> Result<(), Error> { /* Default implementation */ Ok(())} + fn stop(&mut self, _ctx: &mut dyn BundleContext) -> Result<(), Error> { /* Default implementation */ Ok(())} +} + +#[macro_export] +macro_rules! generate_bundle_activator { + ($activator:ty) => { + // fn assert_implements_trait(_: &$activator) { + // fn must_implement<T: celix::BundleActivator>(_t: &T) {} + // must_implement(&*(None::<$activator>).unwrap_or_default()); + // } + + struct ActivatorWrapper { + ctx: Box<dyn $crate::celix::BundleContext>, + activator: $activator, + } + + #[no_mangle] + pub unsafe extern "C" fn celix_bundleActivator_create( + ctx: *mut $crate::celix_bundle_context_t, + out: *mut *mut ::std::ffi::c_void, + ) -> $crate::celix_status_t { + let mut context = $crate::celix::create_bundle_context_instance(ctx); + let activator = <$activator>::new(&mut *context); + let wrapper = ActivatorWrapper { + ctx: context, + activator + }; + *out = Box::into_raw(Box::new(wrapper)) as *mut ::std::ffi::c_void; + $crate::celix::CELIX_SUCCESS + } + + #[no_mangle] + pub unsafe extern "C" fn celix_bundleActivator_start( + handle: *mut ::std::ffi::c_void, + ctx: *mut $crate::celix_bundle_context_t, + ) -> $crate::celix_status_t { + let wrapper = &mut *(handle as *mut ActivatorWrapper); + let result = wrapper.activator.start(&mut *wrapper.ctx); + match result { + Ok(_) => $crate::celix::CELIX_SUCCESS, + Err(e) => e.into(), + } + } + + #[no_mangle] + pub unsafe extern "C" fn celix_bundleActivator_stop( + handle: *mut ::std::ffi::c_void, + ctx: *mut $crate::celix_bundle_context_t, + ) -> $crate::celix_status_t { + let wrapper = &mut *(handle as *mut ActivatorWrapper); + let result = wrapper.activator.stop(&mut *wrapper.ctx); + match result { + Ok(_) => $crate::celix::CELIX_SUCCESS, + Err(e) => e.into(), + } + } + + #[no_mangle] + pub unsafe extern "C" fn celix_bundleActivator_destroy( + handle: *mut ::std::ffi::c_void + ) -> $crate::celix_status_t { + let reclaimed_wrapper = Box::from_raw(handle as *mut ActivatorWrapper); + drop(reclaimed_wrapper); + $crate::celix::CELIX_SUCCESS + } + }; +} diff --git a/misc/experimental/rust/celix_bindings/src/BundleContext.rs b/misc/experimental/rust/celix_bindings/src/celix/bundle_context.rs similarity index 79% rename from misc/experimental/rust/celix_bindings/src/BundleContext.rs rename to misc/experimental/rust/celix_bindings/src/celix/bundle_context.rs index 9dc340b7..b63ae497 100644 --- a/misc/experimental/rust/celix_bindings/src/BundleContext.rs +++ b/misc/experimental/rust/celix_bindings/src/celix/bundle_context.rs @@ -16,6 +16,9 @@ * specific language governing permissions and limitations * under the License. */ + +use celix_bundle_context_t; +use celix_bundleContext_log; use celix_log_level_CELIX_LOG_LEVEL_INFO; pub trait BundleContext { @@ -44,7 +47,13 @@ impl BundleContext for BundleContextImpl { fn log_info(&self, message: &str) { unsafe { - celix_bundleContext_log(self.c_bundle_context, celix_log_level_CELIX_LOG_LEVEL_INFO as u32, message.as_ptr() as *const i8); + //wrap str into CString to ensure null-terminated string + let c_str = std::ffi::CString::new(message).unwrap(); + celix_bundleContext_log(self.c_bundle_context, celix_log_level_CELIX_LOG_LEVEL_INFO as u32, c_str.as_ptr() as *const i8); } } } + +pub fn create_bundle_context_instance(c_bundle_context: *mut celix_bundle_context_t) -> Box<dyn BundleContext> { + Box::new(BundleContextImpl::new(c_bundle_context)) +} diff --git a/misc/experimental/rust/celix_bindings/src/lib.rs b/misc/experimental/rust/celix_bindings/src/celix/errno.rs similarity index 52% copy from misc/experimental/rust/celix_bindings/src/lib.rs copy to misc/experimental/rust/celix_bindings/src/celix/errno.rs index 2e6588d3..ea164b5b 100644 --- a/misc/experimental/rust/celix_bindings/src/lib.rs +++ b/misc/experimental/rust/celix_bindings/src/celix/errno.rs @@ -17,30 +17,29 @@ * 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")); -} -pub use bindings::*; - -//Note C #defines (compile-time constants) are not all generated in the bindings. -pub const CELIX_SUCCESS: celix_status_t = 0; -pub const CELIX_BUNDLE_EXCEPTION: celix_status_t = 70001; +use celix_status_t; -pub mod celix { - use celix_status_t; - use CELIX_SUCCESS; - use CELIX_BUNDLE_EXCEPTION; +pub const BUNDLE_EXCEPTION: celix_status_t = 70001; //TODO move to celix_status_t_CELIX_BUNDLE_EXCEPTION - use celix_bundle_context_t; - use celix_bundleContext_log; +pub enum Error { + BundleException, + CelixStatusError(celix_status_t), // Represent unexpected C API errors +} - use celix_log_helper_t; - use celix_logHelper_create; - use celix_logHelper_log; - use celix_logHelper_destroy; +impl From<celix_status_t> for Error { + fn from(status: celix_status_t) -> Self { + match status { + BUNDLE_EXCEPTION => Error::BundleException, + _ => Error::CelixStatusError(status), + } + } +} - include!("BundleContext.rs"); - include!("BundleActivator.rs"); - include!("LogHelper.rs"); +impl Into<celix_status_t> for Error { + fn into(self) -> celix_status_t { + match self { + Error::BundleException => BUNDLE_EXCEPTION, + Error::CelixStatusError(status) => status, + } + } } diff --git a/misc/experimental/rust/celix_bindings/src/LogHelper.rs b/misc/experimental/rust/celix_bindings/src/celix/log_helper.rs similarity index 93% rename from misc/experimental/rust/celix_bindings/src/LogHelper.rs rename to misc/experimental/rust/celix_bindings/src/celix/log_helper.rs index b168b80c..9f0a43b2 100644 --- a/misc/experimental/rust/celix_bindings/src/LogHelper.rs +++ b/misc/experimental/rust/celix_bindings/src/celix/log_helper.rs @@ -17,6 +17,12 @@ * under the License. */ +use ::celix::BundleContext; +use celix_log_helper_t; +use celix_logHelper_create; +use celix_logHelper_destroy; +use celix_logHelper_log; + #[warn(unused_imports)] pub enum LogLevel { Trace = ::bindings::celix_log_level_CELIX_LOG_LEVEL_TRACE as isize, @@ -27,7 +33,7 @@ pub enum LogLevel { Fatal = ::bindings::celix_log_level_CELIX_LOG_LEVEL_FATAL as isize, } -struct LogHelper { +pub struct LogHelper { celix_log_helper: *mut celix_log_helper_t, } diff --git a/misc/experimental/rust/celix_bindings/src/lib.rs b/misc/experimental/rust/celix_bindings/src/celix/mod.rs similarity index 58% copy from misc/experimental/rust/celix_bindings/src/lib.rs copy to misc/experimental/rust/celix_bindings/src/celix/mod.rs index 2e6588d3..e0c30e20 100644 --- a/misc/experimental/rust/celix_bindings/src/lib.rs +++ b/misc/experimental/rust/celix_bindings/src/celix/mod.rs @@ -17,30 +17,25 @@ * 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")); -} -pub use bindings::*; +use celix_status_t; -//Note C #defines (compile-time constants) are not all generated in the bindings. +//Note C #defines (compile-time constants) are not all generated in the bindings file. +//So introduce them here as constants. pub const CELIX_SUCCESS: celix_status_t = 0; -pub const CELIX_BUNDLE_EXCEPTION: celix_status_t = 70001; -pub mod celix { - use celix_status_t; - use CELIX_SUCCESS; - use CELIX_BUNDLE_EXCEPTION; +mod errno; +// Export errno types in the public API. +pub use self::errno::Error as Error; - use celix_bundle_context_t; - use celix_bundleContext_log; +mod bundle_context; +// Export bundle context types in the public API. +pub use self::bundle_context::BundleContext as BundleContext; +pub use self::bundle_context::create_bundle_context_instance as create_bundle_context_instance; - use celix_log_helper_t; - use celix_logHelper_create; - use celix_logHelper_log; - use celix_logHelper_destroy; +mod bundle_activator; +// Export bundle activator types in the public API. +pub use self::bundle_activator::BundleActivator as BundleActivator; - include!("BundleContext.rs"); - include!("BundleActivator.rs"); - include!("LogHelper.rs"); -} +// mod log_helper; +// // Export log helper types in the public API. +// pub use self::log_helper::LogHelper as LogHelper; diff --git a/misc/experimental/rust/celix_bindings/src/lib.rs b/misc/experimental/rust/celix_bindings/src/lib.rs index 2e6588d3..a07ac3ea 100644 --- a/misc/experimental/rust/celix_bindings/src/lib.rs +++ b/misc/experimental/rust/celix_bindings/src/lib.rs @@ -23,24 +23,4 @@ mod bindings { } pub use bindings::*; -//Note C #defines (compile-time constants) are not all generated in the bindings. -pub const CELIX_SUCCESS: celix_status_t = 0; -pub const CELIX_BUNDLE_EXCEPTION: celix_status_t = 70001; - -pub mod celix { - use celix_status_t; - use CELIX_SUCCESS; - use CELIX_BUNDLE_EXCEPTION; - - use celix_bundle_context_t; - use celix_bundleContext_log; - - use celix_log_helper_t; - use celix_logHelper_create; - use celix_logHelper_log; - use celix_logHelper_destroy; - - include!("BundleContext.rs"); - include!("BundleActivator.rs"); - include!("LogHelper.rs"); -} +pub mod celix; diff --git a/misc/experimental/rust/hello_world_activator/src/lib.rs b/misc/experimental/rust/hello_world_activator/src/lib.rs index 89b6d78c..25390ddf 100644 --- a/misc/experimental/rust/hello_world_activator/src/lib.rs +++ b/misc/experimental/rust/hello_world_activator/src/lib.rs @@ -19,31 +19,27 @@ extern crate celix_bindings; -use std::os::raw::c_void; -use std::ffi::CString; -use std::ffi::NulError; - -//TODO try to remove celix_bindings use statement use celix_bindings::*; //Add all Apache Celix C bindings to the namespace (i.e. celix_bundleContext_log, etc.) use celix::BundleActivator; use celix::BundleContext; +use celix::Error; struct HelloWorldBundle {} impl BundleActivator for HelloWorldBundle { fn new(ctx: &mut dyn celix::BundleContext) -> Self { ctx.log_info("Hello World Bundle Activator created"); - HelloWorldBundle {} + HelloWorldBundle{} } - fn start(&mut self, ctx: &mut dyn BundleContext) -> celix_status_t { + fn start(&mut self, ctx: &mut dyn BundleContext) -> Result<(), Error> { ctx.log_info("Hello World Bundle Activator started"); - CELIX_SUCCESS + Ok(()) } - fn stop(&mut self, ctx: &mut dyn BundleContext) -> celix_status_t { + fn stop(&mut self, ctx: &mut dyn BundleContext) -> Result<(), Error> { ctx.log_info("Hello World Bundle Activator stopped"); - CELIX_SUCCESS + Ok(()) } }