Skip to content

Commit

Permalink
#599: Refactor rust celix lib and add LogHelper to rust celix lib
Browse files Browse the repository at this point in the history
  • Loading branch information
pnoltes committed Aug 20, 2023
1 parent 4c14d8c commit 21b0027
Show file tree
Hide file tree
Showing 9 changed files with 252 additions and 121 deletions.
7 changes: 3 additions & 4 deletions misc/experimental/rust/celix/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,13 @@
# under the License.

[package]
name = "celixs"
name = "celix"
version = "0.0.1"

[build-dependencies]
[dependencies]
celix_bindings = { path = "../celix_bindings" }


[lib]
name = "bindings"
name = "celix"
path = "src/lib.rs"
crate-type = ["rlib"]
70 changes: 30 additions & 40 deletions misc/experimental/rust/celix/src/bundle_activator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,76 +17,66 @@
* under the License.
*/

use ::celix::BundleContext;
use ::celix::Error;
use std::sync::Arc;

use super::BundleContext;
use super::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(())}
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(())}
}

#[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,
ctx: *mut $crate::details::CBundleContext,
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
) -> $crate::details::CStatus {
let boxed_context = $crate::bundle_context_new(ctx);
let mut arc_context = Arc::from(boxed_context);
let activator = <$activator>::new(arc_context);
*out = Box::into_raw(Box::new(activator)) as *mut ::std::ffi::c_void;
$crate::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);
ctx: *mut $crate::details::CBundleContext,
) -> $crate::details::CStatus {
let activator = &mut *(handle as *mut $activator);
let result = activator.start();
match result {
Ok(_) => $crate::celix::CELIX_SUCCESS,
Ok(_) => $crate::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);
ctx: *mut $crate::details::CBundleContext,
) -> $crate::details::CStatus {
let activator = &mut *(handle as *mut $activator);
let result = activator.stop();
match result {
Ok(_) => $crate::celix::CELIX_SUCCESS,
Ok(_) => $crate::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
handle: *mut ::std::ffi::c_void,
_ctx: *mut $crate::details::CBundleContext,
) -> $crate::details::CStatus {
let reclaimed_activator = Box::from_raw(handle as *mut $activator);
drop(reclaimed_activator);
$crate::CELIX_SUCCESS
}
};
}
58 changes: 45 additions & 13 deletions misc/experimental/rust/celix/src/bundle_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,31 @@
* under the License.
*/

use celix_bundle_context_t;
use celix_bundleContext_log;
use celix_log_level_CELIX_LOG_LEVEL_INFO;
use super::LogLevel;

use celix_bindings::celix_bundle_context_t;
use celix_bindings::celix_bundleContext_log;
use celix_bindings::celix_log_level_e;

pub trait BundleContext {
fn get_c_bundle_context(&self) -> *mut celix_bundle_context_t;

fn log(&self, level: LogLevel, message: &str);

fn log_trace(&self, message: &str);

fn log_debug(&self, message: &str);

fn log_info(&self, message: &str);

fn log_warning(&self, message: &str);

fn log_error(&self, message: &str);

fn log_fatal(&self, message: &str);
}

//note BundleContextImpl is pub for usage in bundle activator macro. TODO check if this can be avoided
pub struct BundleContextImpl {
struct BundleContextImpl {
c_bundle_context: *mut celix_bundle_context_t,
}

Expand All @@ -38,22 +51,41 @@ impl BundleContextImpl {
c_bundle_context,
}
}
fn log_to_c(&self, level: LogLevel, message: &str) {
unsafe {
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);
}
Err(e) => {
println!("Error creating CString: {}", e);
}
}
}
}
}

impl BundleContext for BundleContextImpl {
fn get_c_bundle_context(&self) -> *mut celix_bundle_context_t {
self.c_bundle_context
}

fn log_info(&self, message: &str) {
unsafe {
//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);
}
}
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_debug(&self, message: &str) { self.log(LogLevel::Debug, 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_error(&self, message: &str){ self.log(LogLevel::Error, message); }

fn log_fatal(&self, message: &str){ self.log(LogLevel::Fatal, message); }
}

pub fn create_bundle_context_instance(c_bundle_context: *mut celix_bundle_context_t) -> Box<dyn BundleContext> {
pub fn bundle_context_new(c_bundle_context: *mut celix_bundle_context_t) -> Box<dyn BundleContext> {
Box::new(BundleContextImpl::new(c_bundle_context))
}
11 changes: 8 additions & 3 deletions misc/experimental/rust/celix/src/errno.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,18 @@
* under the License.
*/

use celix_status_t;
use celix_bindings::celix_status_t;

pub const CELIX_SUCCESS: celix_status_t = celix_bindings::CELIX_SUCCESS as celix_status_t;

//Note compile-time defined constants are not available in rust generated bindings, so
//these are defined with literal values.
pub const BUNDLE_EXCEPTION: celix_status_t = 70001;

pub const BUNDLE_EXCEPTION: celix_status_t = 70001; //TODO move to celix_status_t_CELIX_BUNDLE_EXCEPTION

pub enum Error {
BundleException,
CelixStatusError(celix_status_t), // Represent unexpected C API errors
CelixStatusError(celix_status_t), // Represent not explicitly mapped celix_status_t values
}

impl From<celix_status_t> for Error {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,37 @@
* under the License.
*/

use celix_status_t;
extern crate celix_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;
// Re-export the celix_status_t and celix_bundle_context_t C API in this crate public API so that
// it can be used in the generate_bundle_activator macro.
// Note that as result the celix rust lib is leaking the celix_status_t and celix_bundle_context_t
// 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;
}

mod errno;
// Export errno types in the public API.
// Re-export errno types in the public API.
pub use self::errno::CELIX_SUCCESS as CELIX_SUCCESS;
pub use self::errno::Error as Error;

mod log_level;
// Re-export log level types in the public API.
pub use self::log_level::LogLevel as LogLevel;

mod bundle_context;
// Export bundle context types in the public API.
// Re-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;
pub use self::bundle_context::bundle_context_new as bundle_context_new;

mod bundle_activator;
// Export bundle activator types in the public API.
// Re-export bundle activator types in the public API.
pub use self::bundle_activator::BundleActivator as BundleActivator;

// mod log_helper;
// // Export log helper types in the public API.
// pub use self::log_helper::LogHelper as LogHelper;
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::log_helper_new as log_helper_new;
Loading

0 comments on commit 21b0027

Please sign in to comment.