/* * 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::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::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, 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(path: *const c_char, flags: c_int, f: F) -> Result 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 $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 $ret> = lib.get($fn_name.as_bytes()).unwrap(); func() } }; }