libloader.rs 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. /*
  2. * Copyright (c) 2006-2025, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2025-10-14 foxglove High-level libdl facade (libloader-style)
  9. */
  10. use core::ffi::{c_char, c_int};
  11. pub use crate::api::libloading as libloading;
  12. pub use libloading::{RTLD_GLOBAL, RTLD_LAZY, RTLD_LOCAL, RTLD_NOW, last_error};
  13. use libloading::{DlError, Library, Symbol};
  14. use crate::println;
  15. /** Open a module with `RTLD_NOW | RTLD_GLOBAL` convenience flags.
  16. Safety: `path` must be a valid NUL-terminated C string pointer.
  17. */
  18. pub unsafe fn dl_open(path: *const c_char) -> Result<Library, DlError> {
  19. Library::open_global(path)
  20. }
  21. /** Open a module with custom flags.
  22. Safety: `path` must be a valid NUL-terminated C string pointer.
  23. */
  24. pub unsafe fn dl_open_with_flags(path: *const c_char, flags: c_int) -> Result<Library, DlError> {
  25. Library::open(path, flags)
  26. }
  27. /** Resolve a typed symbol from a library.
  28. Safety: Caller must ensure `T` matches the actual symbol type.
  29. */
  30. pub unsafe fn dl_sym<'lib, T>(lib: &'lib Library, symbol: *const c_char) -> Result<Symbol<'lib, T>, DlError> {
  31. lib.get_ptr(symbol)
  32. }
  33. pub fn dl_print_last_error() {
  34. println!("libdl error: {}", libloading::DlError::Open(last_error()));
  35. }
  36. /** Use a library for a scoped operation; the library is closed on drop.
  37. Safety: `path` must be a valid NUL-terminated C string pointer.
  38. */
  39. pub unsafe fn with_library<R, F>(path: *const c_char, flags: c_int, f: F) -> Result<R, DlError>
  40. where
  41. F: FnOnce(&Library) -> R,
  42. {
  43. let lib = Library::open(path, flags)?;
  44. let result = f(&lib);
  45. /* Drop will handle closing; return the result */
  46. Ok(result)
  47. }
  48. #[macro_export]
  49. /** Get a function from a dynamic link library
  50. * *You need `use libloader::libloading` first*
  51. * * `lib_path`: the path of DLL
  52. * * `fn_name`: The function name from dll
  53. * * `call_name`: The call function name of `fn_name`
  54. * * `ret`: return type of the function **if the function don't have return value, use "()" instead**
  55. * * `(value: type)`: **(variadic argument)** The arguments of the function from dll
  56. */
  57. macro_rules! get_libfn {
  58. ($lib_path: expr, $fn_name: expr, $call_name: ident, $ret: ty, $($v: ident: $t:ty),*) => {
  59. pub fn $call_name($($v: $t),*) -> $ret {
  60. let lib = $crate::libloader::libloading::Library::new($lib_path).unwrap();
  61. let func: $crate::libloader::libloading::Symbol<fn($($t,)*) -> $ret> = lib.get($fn_name.as_bytes()).unwrap();
  62. func($($v,)*)
  63. }
  64. };
  65. ($lib_path: expr, $fn_name: expr, $call_name:ident, $ret: ty) => {
  66. pub fn $call_name() -> $ret {
  67. let lib = $crate::libloader::libloading::Library::new($lib_path).unwrap();
  68. let func: $crate::libloader::libloading::Symbol<fn() -> $ret> = lib.get($fn_name.as_bytes()).unwrap();
  69. func()
  70. }
  71. };
  72. }