1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
//! Provides shared library access for Unix like systems.
use crate::{core::optional::NSTDOptional, NSTDAny, NSTDAnyMut, NSTDChar, NSTD_NULL};
use libc::{dlclose, dlopen, dlsym, RTLD_LAZY, RTLD_LOCAL};
use nstdapi::nstdapi;

/// Represents an owned handle to a dynamically loaded library.
#[nstdapi]
pub struct NSTDUnixSharedLib {
    /// A raw handle to the shared library.
    handle: NSTDAnyMut,
}
impl Drop for NSTDUnixSharedLib {
    /// [NSTDUnixSharedLib]'s destructor.
    #[inline]
    fn drop(&mut self) {
        // SAFETY: `self.handle` is valid.
        unsafe { dlclose(self.handle) };
    }
}
// SAFETY: `NSTDUnixSharedLib` owns a handle to the dynamically loaded library.
unsafe impl Send for NSTDUnixSharedLib {}
// SAFETY: `NSTDUnixSharedLib` does not undergo interior mutability.
unsafe impl Sync for NSTDUnixSharedLib {}

/// Represents an optional `NSTDUnixSharedLib`.
pub type NSTDUnixOptionalSharedLib = NSTDOptional<NSTDUnixSharedLib>;

/// Loads a dynamically loaded shared library.
///
/// # Parameters:
///
/// - `const NSTDChar *path` - A path to the shared library to load.
///
/// # Returns
///
/// `NSTDUnixOptionalSharedLib lib` - A handle to the loaded library.
///
/// # Safety
///
/// See <https://man7.org/linux/man-pages/man3/dlopen.3.html>.
#[inline]
#[nstdapi]
pub unsafe fn nstd_os_unix_shared_lib_load(path: *const NSTDChar) -> NSTDUnixOptionalSharedLib {
    match dlopen(path, RTLD_LAZY | RTLD_LOCAL) {
        NSTD_NULL => NSTDOptional::None,
        handle => NSTDOptional::Some(NSTDUnixSharedLib { handle }),
    }
}

/// Returns a raw handle to a dynamically loaded library.
///
/// # Parameters:
///
/// - `const NSTDUnixSharedLib *lib` - The shared library.
///
/// # Returns
///
/// `NSTDAnyMut handle` - A raw handle to the dynamically loaded library.
#[inline]
#[nstdapi]
pub fn nstd_os_unix_shared_lib_handle(lib: &NSTDUnixSharedLib) -> NSTDAnyMut {
    lib.handle
}

/// Returns an immutable opaque pointer to a symbol in a loaded library.
///
/// # Parameters:
///
/// - `const NSTDUnixSharedLib *lib` - The shared library.
///
/// - `const NSTDChar *symbol` - The symbol to retrieve a pointer to.
///
/// # Returns
///
/// `NSTDAny ptr` - A pointer to the loaded symbol, null on error.
///
/// # Safety
///
/// See <https://man7.org/linux/man-pages/man3/dlsym.3.html>.
#[inline]
#[nstdapi]
pub unsafe fn nstd_os_unix_shared_lib_get(
    lib: &NSTDUnixSharedLib,
    symbol: *const NSTDChar,
) -> NSTDAny {
    dlsym(lib.handle, symbol)
}

/// Returns a mutable opaque pointer to a symbol in a loaded library.
///
/// # Parameters:
///
/// - `NSTDUnixSharedLib *lib` - The shared library.
///
/// - `const NSTDChar *symbol` - The symbol to retrieve a pointer to.
///
/// # Returns
///
/// `NSTDAnyMut ptr` - A pointer to the loaded symbol, null on error.
///
/// # Safety
///
/// See <https://man7.org/linux/man-pages/man3/dlsym.3.html>.
#[inline]
#[nstdapi]
pub unsafe fn nstd_os_unix_shared_lib_get_mut(
    lib: &mut NSTDUnixSharedLib,
    symbol: *const NSTDChar,
) -> NSTDAnyMut {
    dlsym(lib.handle, symbol)
}

/// Closes and frees a loaded shared library.
///
/// # Parameters:
///
/// - `NSTDUnixSharedLib lib` - A handle to the loaded library to unload.
///
/// # Safety
///
/// See <https://man7.org/linux/man-pages/man3/dlclose.3p.html>.
#[inline]
#[nstdapi]
#[allow(unused_variables)]
pub fn nstd_os_unix_shared_lib_free(lib: NSTDUnixSharedLib) {}