makepad_platform/os/linux/
module_loader.rs

1use self::super::libc_sys::{dlclose, dlopen, dlsym, RTLD_LAZY, RTLD_LOCAL};
2use std::{ffi::CString, ptr::NonNull};
3
4/// A module loader for loading shared libraries.
5pub struct ModuleLoader(::std::ptr::NonNull<::std::os::raw::c_void>);
6
7impl ModuleLoader {
8    /// Load a shared library by its path.
9    pub fn load(path: &str) -> Result<Self, ()> {
10        let path = CString::new(path).unwrap();
11
12        // Open the shared library with lazy loading and local visibility.
13        let module = unsafe { dlopen(path.as_ptr(), RTLD_LAZY | RTLD_LOCAL) };
14        if module.is_null() {
15            Err(())
16        } else {
17            Ok(ModuleLoader(unsafe { NonNull::new_unchecked(module) }))
18        }
19    }
20
21    /// Get a symbol from the loaded module.
22    pub fn get_symbol<F: Sized>(&self, name: &str) -> Result<F, ()> {
23        let name = CString::new(name).unwrap();
24
25        let symbol = unsafe { dlsym(self.0.as_ptr(), name.as_ptr()) };
26
27        if symbol.is_null() {
28            return Err(());
29        }
30
31        // Transmute the symbol to the desired type.
32        Ok(unsafe { std::mem::transmute_copy::<_, F>(&symbol) })
33    }
34}
35
36impl Drop for ModuleLoader {
37    fn drop(&mut self) {
38        // When the module loader is dropped, close the shared library.
39        unsafe { dlclose(self.0.as_ptr()) };
40    }
41}