summaryrefslogtreecommitdiff
path: root/components/rust/core/src/libloader.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/rust/core/src/libloader.rs')
-rw-r--r--components/rust/core/src/libloader.rs83
1 files changed, 83 insertions, 0 deletions
diff --git a/components/rust/core/src/libloader.rs b/components/rust/core/src/libloader.rs
new file mode 100644
index 0000000000..5fb66d98a9
--- /dev/null
+++ b/components/rust/core/src/libloader.rs
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2006-2025, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2025-10-14 foxglove High-level libdl facade (libloader-style)
+ */
+
+use core::ffi::{c_char, c_int};
+pub use crate::api::libloading as libloading;
+pub use libloading::{RTLD_GLOBAL, RTLD_LAZY, RTLD_LOCAL, RTLD_NOW, last_error};
+use libloading::{DlError, Library, Symbol};
+use crate::println;
+
+/** Open a module with `RTLD_NOW | RTLD_GLOBAL` convenience flags.
+
+Safety: `path` must be a valid NUL-terminated C string pointer.
+*/
+pub unsafe fn dl_open(path: *const c_char) -> Result<Library, DlError> {
+ Library::open_global(path)
+}
+
+/** Open a module with custom flags.
+
+Safety: `path` must be a valid NUL-terminated C string pointer.
+*/
+pub unsafe fn dl_open_with_flags(path: *const c_char, flags: c_int) -> Result<Library, DlError> {
+ Library::open(path, flags)
+}
+
+/** Resolve a typed symbol from a library.
+
+Safety: Caller must ensure `T` matches the actual symbol type.
+*/
+pub unsafe fn dl_sym<'lib, T>(lib: &'lib Library, symbol: *const c_char) -> Result<Symbol<'lib, T>, DlError> {
+ lib.get_ptr(symbol)
+}
+
+pub fn dl_print_last_error() {
+ println!("libdl error: {}", libloading::DlError::Open(last_error()));
+}
+
+/** Use a library for a scoped operation; the library is closed on drop.
+
+Safety: `path` must be a valid NUL-terminated C string pointer.
+*/
+pub unsafe fn with_library<R, F>(path: *const c_char, flags: c_int, f: F) -> Result<R, DlError>
+where
+ F: FnOnce(&Library) -> R,
+{
+ let lib = Library::open(path, flags)?;
+ let result = f(&lib);
+ /* Drop will handle closing; return the result */
+ Ok(result)
+}
+
+#[macro_export]
+/** Get a function from a dynamic link library
+ * *You need `use libloader::libloading` first*
+ * * `lib_path`: the path of DLL
+ * * `fn_name`: The function name from dll
+ * * `call_name`: The call function name of `fn_name`
+ * * `ret`: return type of the function **if the function don't have return value, use "()" instead**
+ * * `(value: type)`: **(variadic argument)** The arguments of the function from dll
+ */
+macro_rules! get_libfn {
+ ($lib_path: expr, $fn_name: expr, $call_name: ident, $ret: ty, $($v: ident: $t:ty),*) => {
+ pub fn $call_name($($v: $t),*) -> $ret {
+ let lib = $crate::libloader::libloading::Library::new($lib_path).unwrap();
+ let func: $crate::libloader::libloading::Symbol<fn($($t,)*) -> $ret> = lib.get($fn_name.as_bytes()).unwrap();
+ func($($v,)*)
+ }
+ };
+ ($lib_path: expr, $fn_name: expr, $call_name:ident, $ret: ty) => {
+ pub fn $call_name() -> $ret {
+ let lib = $crate::libloader::libloading::Library::new($lib_path).unwrap();
+ let func: $crate::libloader::libloading::Symbol<fn() -> $ret> = lib.get($fn_name.as_bytes()).unwrap();
+ func()
+ }
+ };
+}