mirror of
https://github.com/openharmony/third_party_rust_libloading.git
synced 2026-07-19 13:16:19 -04:00
Significantly improve documentation
With these improvements browsing the documentation for os-specific functionality should be possible from any system. In particular UNIX documentation now has information on Windows and the Windows documentation has information on UNIX-specific stuff.
This commit is contained in:
committed by
Simonas Kazlauskas
parent
76e2d46e9e
commit
08cfc8f9c0
@@ -16,3 +16,7 @@ features = [
|
||||
"errhandlingapi",
|
||||
"libloaderapi",
|
||||
]
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
rustdoc-args = ["--cfg", "docsrs"]
|
||||
|
||||
+35
-8
@@ -1,5 +1,6 @@
|
||||
use std::ffi::CString;
|
||||
|
||||
/// A `dlerror` error.
|
||||
pub struct DlDescription(pub(crate) CString);
|
||||
|
||||
impl std::fmt::Debug for DlDescription {
|
||||
@@ -8,6 +9,7 @@ impl std::fmt::Debug for DlDescription {
|
||||
}
|
||||
}
|
||||
|
||||
/// A Windows API error.
|
||||
pub struct WindowsError(pub(crate) std::io::Error);
|
||||
|
||||
impl std::fmt::Debug for WindowsError {
|
||||
@@ -16,23 +18,36 @@ impl std::fmt::Debug for WindowsError {
|
||||
}
|
||||
}
|
||||
|
||||
/// Errors.
|
||||
#[derive(Debug)]
|
||||
#[non_exhaustive]
|
||||
pub enum Error {
|
||||
/// The `dlopen` call failed.
|
||||
DlOpen { desc: DlDescription },
|
||||
DlOpen {
|
||||
/// The source error.
|
||||
desc: DlDescription
|
||||
},
|
||||
/// The `dlopen` call failed and system did not report an error.
|
||||
DlOpenUnknown,
|
||||
/// The `dlsym` call failed.
|
||||
DlSym { desc: DlDescription },
|
||||
DlSym {
|
||||
/// The source error.
|
||||
desc: DlDescription
|
||||
},
|
||||
/// The `dlsym` call failed and system did not report an error.
|
||||
DlSymUnknown,
|
||||
/// The `dlclose` call failed.
|
||||
DlClose { desc: DlDescription },
|
||||
DlClose {
|
||||
/// The source error.
|
||||
desc: DlDescription
|
||||
},
|
||||
/// The `dlclose` call failed and system did not report an error.
|
||||
DlCloseUnknown,
|
||||
/// The `LoadLibraryW` call failed.
|
||||
LoadLibraryW { source: WindowsError },
|
||||
LoadLibraryW {
|
||||
/// The source error.
|
||||
source: WindowsError
|
||||
},
|
||||
/// The `LoadLibraryW` call failed and system did not report an error.
|
||||
LoadLibraryWUnknown,
|
||||
/// The `GetModuleHandleExW` call failed.
|
||||
@@ -43,19 +58,31 @@ pub enum Error {
|
||||
/// The `LoadLibraryW` call failed and system did not report an error.
|
||||
GetModuleHandleExWUnknown,
|
||||
/// The `GetProcAddress` call failed.
|
||||
GetProcAddress { source: WindowsError },
|
||||
GetProcAddress {
|
||||
/// The source error.
|
||||
source: WindowsError
|
||||
},
|
||||
/// The `GetProcAddressUnknown` call failed and system did not report an error.
|
||||
GetProcAddressUnknown,
|
||||
/// The `FreeLibrary` call failed.
|
||||
FreeLibrary { source: WindowsError },
|
||||
FreeLibrary {
|
||||
/// The source error.
|
||||
source: WindowsError
|
||||
},
|
||||
/// The `FreeLibrary` call failed and system did not report an error.
|
||||
FreeLibraryUnknown,
|
||||
/// The requested type cannot possibly work.
|
||||
IncompatibleSize,
|
||||
/// Could not create a new CString.
|
||||
CreateCString { source: std::ffi::NulError },
|
||||
CreateCString {
|
||||
/// The source error.
|
||||
source: std::ffi::NulError
|
||||
},
|
||||
/// Could not create a new CString from bytes with trailing null.
|
||||
CreateCStringWithTrailing { source: std::ffi::FromBytesWithNulError },
|
||||
CreateCStringWithTrailing {
|
||||
/// The source error.
|
||||
source: std::ffi::FromBytesWithNulError
|
||||
},
|
||||
}
|
||||
|
||||
impl std::error::Error for Error {
|
||||
|
||||
+24
-13
@@ -36,6 +36,16 @@
|
||||
//!
|
||||
//! The compiler will ensure that the loaded `function` will not outlive the `Library` it comes
|
||||
//! from, preventing a common cause of undefined behaviour and memory safety problems.
|
||||
#![deny(
|
||||
missing_docs,
|
||||
clippy::all,
|
||||
unreachable_pub,
|
||||
unused,
|
||||
)]
|
||||
#![cfg_attr(docsrs, deny(broken_intra_doc_links))]
|
||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||
|
||||
|
||||
use std::ffi::OsStr;
|
||||
use std::fmt;
|
||||
use std::ops;
|
||||
@@ -64,7 +74,7 @@ impl Library {
|
||||
/// * Absolute path to the library;
|
||||
/// * Relative (to the current working directory) path to the library.
|
||||
///
|
||||
/// ## Thread-safety
|
||||
/// # Thread-safety
|
||||
///
|
||||
/// The implementation strives to be as MT-safe as sanely possible, however due to certain
|
||||
/// error-handling related resources not always being safe, this library is not MT-safe either.
|
||||
@@ -80,12 +90,12 @@ impl Library {
|
||||
/// path-less filename and library search path is modified (`SetDllDirectory` function on
|
||||
/// Windows, `{DY,}LD_LIBRARY_PATH` environment variable on UNIX).
|
||||
///
|
||||
/// ## Platform-specific behaviour
|
||||
/// # Platform-specific behaviour
|
||||
///
|
||||
/// When a plain library filename is supplied, locations where library is searched for is
|
||||
/// platform specific and cannot be adjusted in a portable manner.
|
||||
///
|
||||
/// ### Windows
|
||||
/// ## Windows
|
||||
///
|
||||
/// If the `filename` specifies a library filename without path and with extension omitted,
|
||||
/// `.dll` extension is implicitly added. This behaviour may be suppressed by appending a
|
||||
@@ -95,7 +105,7 @@ impl Library {
|
||||
/// `#[thread_local]` attributes), loading the library will fail on versions prior to Windows
|
||||
/// Vista.
|
||||
///
|
||||
/// ## Tips
|
||||
/// # Tips
|
||||
///
|
||||
/// Distributing your dynamic libraries under a filename common to all platforms (e.g.
|
||||
/// `awesome.module`) allows to avoid code which has to account for platform’s conventional
|
||||
@@ -105,7 +115,7 @@ impl Library {
|
||||
/// are being loaded. Platform-dependent library search locations combined with various quirks
|
||||
/// related to path-less filenames may cause flaky code.
|
||||
///
|
||||
/// ## Examples
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use ::libloading::Library;
|
||||
@@ -126,12 +136,12 @@ impl Library {
|
||||
/// Symbol is interpreted as-is; no mangling is done. This means that symbols like `x::y` are
|
||||
/// most likely invalid.
|
||||
///
|
||||
/// ## Unsafety
|
||||
/// # Safety
|
||||
///
|
||||
/// Pointer to a value of arbitrary type is returned. Using a value with wrong type is
|
||||
/// undefined.
|
||||
///
|
||||
/// ## Platform-specific behaviour
|
||||
/// # Platform-specific behaviour
|
||||
///
|
||||
/// On Linux and Windows, a TLS variable acts just like any regular global variable. OS X uses
|
||||
/// some sort of lazy initialization scheme, which makes loading TLS variables this way
|
||||
@@ -143,7 +153,7 @@ impl Library {
|
||||
/// pointer without it being an error. If loading a null pointer is something you care about,
|
||||
/// consider using the [`os::unix::Library::get_singlethreaded`] call.
|
||||
///
|
||||
/// ## Examples
|
||||
/// # Examples
|
||||
///
|
||||
/// Given a loaded library:
|
||||
///
|
||||
@@ -232,12 +242,13 @@ pub struct Symbol<'lib, T: 'lib> {
|
||||
impl<'lib, T> Symbol<'lib, T> {
|
||||
/// Extract the wrapped `os::platform::Symbol`.
|
||||
///
|
||||
/// ## Unsafety
|
||||
/// # Safety
|
||||
///
|
||||
/// Using this function relinquishes all the lifetime guarantees. It is up to programmer to
|
||||
/// ensure the resulting `Symbol` is not used past the lifetime of the `Library` this symbol
|
||||
/// was loaded from.
|
||||
///
|
||||
/// ## Examples
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use ::libloading::{Library, Symbol};
|
||||
@@ -256,12 +267,12 @@ impl<'lib, T> Symbol<'lib, T> {
|
||||
/// Note that, in order to create association between the symbol and the library this symbol
|
||||
/// came from, this function requires reference to the library provided.
|
||||
///
|
||||
/// ## Unsafety
|
||||
/// # Safety
|
||||
///
|
||||
/// It is invalid to provide a reference to any other value other than the library the `sym`
|
||||
/// was loaded from. Doing so invalidates any lifetime guarantees.
|
||||
///
|
||||
/// ## Examples
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use ::libloading::{Library, Symbol};
|
||||
@@ -283,7 +294,7 @@ impl<'lib, T> Symbol<'lib, T> {
|
||||
impl<'lib, T> Symbol<'lib, Option<T>> {
|
||||
/// Lift Option out of the symbol.
|
||||
///
|
||||
/// ## Examples
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use ::libloading::{Library, Symbol};
|
||||
|
||||
+8
-26
@@ -16,30 +16,12 @@
|
||||
//! use libloading::os::windows::*;
|
||||
//! ```
|
||||
|
||||
macro_rules! unix {
|
||||
($item: item) => {
|
||||
/// UNIX implementation of dynamic library loading.
|
||||
///
|
||||
/// This module should be expanded with more UNIX-specific functionality in the future.
|
||||
$item
|
||||
}
|
||||
}
|
||||
/// UNIX implementation of dynamic library loading.
|
||||
#[cfg(any(unix, docsrs))]
|
||||
#[cfg_attr(docsrs, doc(cfg(unix)))]
|
||||
pub mod unix;
|
||||
|
||||
macro_rules! windows {
|
||||
($item: item) => {
|
||||
/// Windows implementation of dynamic library loading.
|
||||
///
|
||||
/// This module should be expanded with more Windows-specific functionality in the future.
|
||||
$item
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
unix!(pub mod unix;);
|
||||
#[cfg(unix)]
|
||||
windows!(pub mod windows {});
|
||||
|
||||
#[cfg(windows)]
|
||||
windows!(pub mod windows;);
|
||||
#[cfg(windows)]
|
||||
unix!(pub mod unix {});
|
||||
/// Windows implementation of dynamic library loading.
|
||||
#[cfg(any(windows, docsrs))]
|
||||
#[cfg_attr(docsrs, doc(cfg(windows)))]
|
||||
pub mod windows;
|
||||
|
||||
+54
-36
@@ -1,9 +1,19 @@
|
||||
use util::{ensure_compatible_types, cstr_cow_from_bytes};
|
||||
// A hack for docs.rs to build documentation that has both windows and linux documentation in the
|
||||
// same rustdoc build visible.
|
||||
#[cfg(all(docsrs, not(unix)))]
|
||||
mod unix_imports {
|
||||
}
|
||||
#[cfg(unix)]
|
||||
mod unix_imports {
|
||||
pub(super) use std::os::unix::ffi::OsStrExt;
|
||||
}
|
||||
|
||||
use self::unix_imports::*;
|
||||
use util::{ensure_compatible_types, cstr_cow_from_bytes};
|
||||
use std::ffi::{CStr, OsStr};
|
||||
use std::{fmt, marker, mem, ptr};
|
||||
use std::os::raw;
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
|
||||
|
||||
// dl* family of functions did not have enough thought put into it.
|
||||
//
|
||||
@@ -61,7 +71,7 @@ where F: FnOnce() -> Option<T> {
|
||||
})
|
||||
}
|
||||
|
||||
/// A platform-specific equivalent of the cross-platform `Library`.
|
||||
/// A platform-specific counterpart of the cross-platform [`Library`](crate::Library).
|
||||
pub struct Library {
|
||||
handle: *mut raw::c_void
|
||||
}
|
||||
@@ -85,34 +95,45 @@ unsafe impl Send for Library {}
|
||||
unsafe impl Sync for Library {}
|
||||
|
||||
impl Library {
|
||||
/// Find and load a shared library (module).
|
||||
/// Find and eagerly load a shared library (module).
|
||||
///
|
||||
/// Locations where library is searched for is platform specific and can’t be adjusted
|
||||
/// portably.
|
||||
/// If the `filename` contains a [path separator], the `filename` is interpreted as a `path` to
|
||||
/// a file. Otherwise, platform-specific algorithms are employed to find a library with a
|
||||
/// matching file name.
|
||||
///
|
||||
/// Corresponds to `dlopen(filename, RTLD_NOW)`.
|
||||
/// This is equivalent to [`Library::open`]`(filename, RTLD_NOW)`.
|
||||
///
|
||||
/// [path separator]: std::path::MAIN_SEPARATOR
|
||||
#[inline]
|
||||
pub fn new<P: AsRef<OsStr>>(filename: P) -> Result<Library, crate::Error> {
|
||||
Library::open(Some(filename), RTLD_NOW)
|
||||
}
|
||||
|
||||
/// Load the dynamic libraries linked into main program.
|
||||
/// Eagerly load the `Library` representing the current executable.
|
||||
///
|
||||
/// This allows retrieving symbols from any **dynamic** library linked into the program,
|
||||
/// without specifying the exact library.
|
||||
/// [`Library::get`] calls of the returned `Library` will look for symbols in following
|
||||
/// locations in order:
|
||||
///
|
||||
/// Corresponds to `dlopen(NULL, RTLD_NOW)`.
|
||||
/// 1. Original program image;
|
||||
/// 2. Any executable object files (e.g. shared libraries) loaded at program startup;
|
||||
/// 3. Executable object files loaded at runtime (e.g. via other `Library::new` calls or via
|
||||
/// calls to the `dlopen` function)
|
||||
///
|
||||
/// Note that behaviour of `Library` loaded with this method is different from
|
||||
/// Libraries loaded with [`os::windows::Library::this`].
|
||||
///
|
||||
/// This is equivalent to [`Library::open`]`(None, RTLD_NOW)`.
|
||||
///
|
||||
/// [`os::windows::Library::this`]: crate::os::windows::Library::this
|
||||
#[inline]
|
||||
pub fn this() -> Library {
|
||||
Library::open(None::<&OsStr>, RTLD_NOW).expect("this should never fail")
|
||||
}
|
||||
|
||||
/// Find and load a shared library (module).
|
||||
/// Find and load an executable object file (shared library).
|
||||
///
|
||||
/// Locations where library is searched for is platform specific and can’t be adjusted
|
||||
/// portably.
|
||||
///
|
||||
/// If the `filename` is None, null pointer is passed to `dlopen`.
|
||||
/// See documentation for [`Library::this`] for further description of behaviour
|
||||
/// when the `filename` is `None`. Otherwise see [`Library::new`].
|
||||
///
|
||||
/// Corresponds to `dlopen(filename, flags)`.
|
||||
pub fn open<P>(filename: Option<P>, flags: raw::c_int) -> Result<Library, crate::Error>
|
||||
@@ -174,29 +195,27 @@ impl Library {
|
||||
/// Get a pointer to function or static variable by symbol name.
|
||||
///
|
||||
/// The `symbol` may not contain any null bytes, with an exception of last byte. A null
|
||||
/// terminated `symbol` may avoid a string allocation in some cases.
|
||||
/// terminated `symbol` may avoid an allocation in some cases.
|
||||
///
|
||||
/// Symbol is interpreted as-is; no mangling is done. This means that symbols like `x::y` are
|
||||
/// most likely invalid.
|
||||
///
|
||||
/// ## Unsafety
|
||||
/// # Safety
|
||||
///
|
||||
/// This function does not validate the type `T`. It is up to the user of this function to
|
||||
/// ensure that the loaded symbol is in fact a `T`. Using a value with a wrong type has no
|
||||
/// definied behaviour.
|
||||
/// defined behaviour.
|
||||
///
|
||||
///
|
||||
///
|
||||
/// ## Platform-specific behaviour
|
||||
/// # Platform-specific behaviour
|
||||
///
|
||||
/// OS X uses some sort of lazy initialization scheme, which makes loading TLS variables
|
||||
/// impossible. Using a TLS variable loaded this way on OS X is undefined behaviour.
|
||||
/// impossible. Using a TLS variable loaded this way on OS X has no defined behaviour.
|
||||
///
|
||||
/// On POSIX implementations where the `dlerror` function is not confirmed to be MT-safe (such
|
||||
/// as FreeBSD), this function will unconditionally return an error the underlying `dlsym` call
|
||||
/// returns a null pointer. There are rare situations where `dlsym` returns a genuine null
|
||||
/// pointer without it being an error. If loading a null pointer is something you care about,
|
||||
/// consider using the [`Library::get_singlethreaded`] call.
|
||||
/// as FreeBSD), this function will unconditionally return an error when the underlying `dlsym`
|
||||
/// call returns a null pointer. There are rare situations where `dlsym` returns a genuine null
|
||||
/// pointer without it being an error. If loading a symbol at null address is something you
|
||||
/// care about, consider using the [`Library::get_singlethreaded`] call.
|
||||
#[inline(always)]
|
||||
pub unsafe fn get<T>(&self, symbol: &[u8]) -> Result<Symbol<T>, crate::Error> {
|
||||
#[cfg(mtsafe_dlerror)]
|
||||
@@ -215,20 +234,20 @@ impl Library {
|
||||
/// Symbol is interpreted as-is; no mangling is done. This means that symbols like `x::y` are
|
||||
/// most likely invalid.
|
||||
///
|
||||
/// ## Unsafety
|
||||
/// # Safety
|
||||
///
|
||||
/// This function does not validate the type `T`. It is up to the user of this function to
|
||||
/// ensure that the loaded symbol is in fact a `T`. Using a value with a wrong type has no
|
||||
/// definied behaviour.
|
||||
/// defined behaviour.
|
||||
///
|
||||
/// It is up to the user of this library to ensure that no other calls to an MT-unsafe
|
||||
/// implementation of `dlerror` occur while this function is executing. Failing that the
|
||||
/// results of this function are not defined.
|
||||
/// implementation of `dlerror` occur during execution of this function. Failing that, the
|
||||
/// behaviour of this function is not defined.
|
||||
///
|
||||
/// ## Platform-specific behaviour
|
||||
/// # Platform-specific behaviour
|
||||
///
|
||||
/// OS X uses some sort of lazy initialization scheme, which makes loading TLS variables
|
||||
/// impossible. Using a TLS variable loaded this way on OS X is undefined behaviour.
|
||||
/// impossible. Using a TLS variable loaded this way on OS X has no defined behaviour.
|
||||
#[inline(always)]
|
||||
pub unsafe fn get_singlethreaded<T>(&self, symbol: &[u8]) -> Result<Symbol<T>, crate::Error> {
|
||||
self.get_impl(symbol, || Ok(Symbol {
|
||||
@@ -249,7 +268,7 @@ impl Library {
|
||||
|
||||
/// Convert a raw handle returned by `dlopen`-family of calls to a `Library`.
|
||||
///
|
||||
/// ## Unsafety
|
||||
/// # Safety
|
||||
///
|
||||
/// The pointer shall be a result of a successful call of the `dlopen`-family of functions or a
|
||||
/// pointer previously returned by `Library::into_raw` call. It must be valid to call `dlclose`
|
||||
@@ -266,8 +285,7 @@ impl Library {
|
||||
/// what library was opened or other platform specifics.
|
||||
///
|
||||
/// You only need to call this if you are interested in handling any errors that may arise when
|
||||
/// library is unloaded. Otherwise the implementation of `Drop` for `Library` will close the
|
||||
/// library and ignore the errors were they arise.
|
||||
/// library is unloaded. Otherwise this will be done when `Library` is dropped.
|
||||
pub fn close(self) -> Result<(), crate::Error> {
|
||||
let result = with_dlerror(|desc| crate::Error::DlClose { desc }, || {
|
||||
if unsafe { dlclose(self.handle) } == 0 {
|
||||
|
||||
+49
-23
@@ -1,17 +1,31 @@
|
||||
extern crate winapi;
|
||||
use self::winapi::shared::minwindef::{WORD, DWORD, HMODULE, FARPROC};
|
||||
use self::winapi::shared::ntdef::WCHAR;
|
||||
use self::winapi::shared::winerror;
|
||||
use self::winapi::um::{errhandlingapi, libloaderapi};
|
||||
// A hack for docs.rs to build documentation that has both windows and linux documentation in the
|
||||
// same rustdoc build visible.
|
||||
#[cfg(all(docsrs, not(windows)))]
|
||||
mod windows_imports {
|
||||
pub(super) enum WORD {}
|
||||
pub(super) enum DWORD {}
|
||||
pub(super) enum HMODULE {}
|
||||
pub(super) enum FARPROC {}
|
||||
}
|
||||
#[cfg(windows)]
|
||||
mod windows_imports {
|
||||
extern crate winapi;
|
||||
pub(super) use self::winapi::shared::minwindef::{WORD, DWORD, HMODULE, FARPROC};
|
||||
pub(super) use self::winapi::shared::ntdef::WCHAR;
|
||||
pub(super) use self::winapi::shared::winerror;
|
||||
pub(super) use self::winapi::um::{errhandlingapi, libloaderapi};
|
||||
pub(super) use std::os::windows::ffi::{OsStrExt, OsStringExt};
|
||||
pub(super) const SEM_FAILCE: DWORD = 1;
|
||||
}
|
||||
|
||||
use self::windows_imports::*;
|
||||
use util::{ensure_compatible_types, cstr_cow_from_bytes};
|
||||
|
||||
use std::ffi::{OsStr, OsString};
|
||||
use std::{fmt, io, marker, mem, ptr};
|
||||
use std::os::windows::ffi::{OsStrExt, OsStringExt};
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
/// A platform-specific equivalent of the cross-platform `Library`.
|
||||
/// A platform-specific counterpart of the cross-platform [`Library`](crate::Library).
|
||||
pub struct Library(HMODULE);
|
||||
|
||||
unsafe impl Send for Library {}
|
||||
@@ -31,9 +45,16 @@ unsafe impl Send for Library {}
|
||||
unsafe impl Sync for Library {}
|
||||
|
||||
impl Library {
|
||||
/// Find and load a shared library (module).
|
||||
/// Find and load a module.
|
||||
///
|
||||
/// Corresponds to `LoadLibraryW(filename, reserved: NULL, flags: 0)` which is equivalent to `LoadLibraryW(filename)`
|
||||
/// If the `filename` specifies a full path, the function only searches that path for the
|
||||
/// module. Otherwise, if the `filename` specifies a relative path or a module name without a
|
||||
/// path, the function uses a windows-specific search strategy to find the module; for more
|
||||
/// information, see the [Remarks on MSDN][msdn].
|
||||
///
|
||||
/// This is equivalent to [`Library::load_with_flags`]`(filename, 0)`.
|
||||
///
|
||||
/// [msdn]: https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryw#remarks
|
||||
#[inline]
|
||||
pub fn new<P: AsRef<OsStr>>(filename: P) -> Result<Library, crate::Error> {
|
||||
Library::load_with_flags(filename, 0)
|
||||
@@ -41,12 +62,16 @@ impl Library {
|
||||
|
||||
/// Load the `Library` representing the original program executable.
|
||||
///
|
||||
/// Note that this is not a direct equivalent to [`os::unix::Library::this`].
|
||||
/// Note that behaviour of `Library` loaded with this method is different from
|
||||
/// Libraries loaded with [`os::unix::Library::this`]. For more information refer to [MSDN].
|
||||
///
|
||||
/// Corresponds to `GetModuleHandleExW(0, NULL, _)`.
|
||||
///
|
||||
/// [`os::unix::Library::this`]: crate::os::unix::Library::this
|
||||
/// [MSDN]: https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulehandleexw
|
||||
pub fn this() -> Result<Library, crate::Error> {
|
||||
let handle = unsafe {
|
||||
let handle: HMODULE = std::ptr::null_mut();
|
||||
unsafe {
|
||||
let mut handle: HMODULE = std::ptr::null_mut();
|
||||
with_get_last_error(|source| crate::Error::GetModuleHandleExW { source }, || {
|
||||
let result = libloaderapi::GetModuleHandleExW(0, std::ptr::null_mut(), &mut handle);
|
||||
if result == 0 {
|
||||
@@ -54,16 +79,18 @@ impl Library {
|
||||
} else {
|
||||
Some(Library(handle))
|
||||
}
|
||||
}).map_err(|e| e.unwrap_or(crate::Error::GetModuleHandleExWUnknown));
|
||||
};
|
||||
}).map_err(|e| e.unwrap_or(crate::Error::GetModuleHandleExWUnknown))
|
||||
}
|
||||
}
|
||||
|
||||
/// Find and load a shared library (module).
|
||||
/// Find and load a module, additionally adjusting behaviour with flags.
|
||||
///
|
||||
/// Locations where library is searched for is platform specific and can’t be adjusted
|
||||
/// portably.
|
||||
/// See [`Library::new`] for documentation on handling of the `filename` argument. See the
|
||||
/// [flag table on MSDN][flags] for information on applicable values for the `flags` argument.
|
||||
///
|
||||
/// Corresponds to `LoadLibraryW(filename, reserved: NULL, flags)`.
|
||||
/// Corresponds to `LoadLibraryExW(filename, reserved: NULL, flags)`.
|
||||
///
|
||||
/// [flags]: https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters
|
||||
pub fn load_with_flags<P: AsRef<OsStr>>(filename: P, flags: DWORD) -> Result<Library, crate::Error> {
|
||||
let wide_filename: Vec<u16> = filename.as_ref().encode_wide().chain(Some(0)).collect();
|
||||
let _guard = ErrorModeGuard::new();
|
||||
@@ -93,7 +120,7 @@ impl Library {
|
||||
/// Symbol is interpreted as-is; no mangling is done. This means that symbols like `x::y` are
|
||||
/// most likely invalid.
|
||||
///
|
||||
/// ## Unsafety
|
||||
/// # Safety
|
||||
///
|
||||
/// This function does not validate the type `T`. It is up to the user of this function to
|
||||
/// ensure that the loaded symbol is in fact a `T`. Using a value with a wrong type has no
|
||||
@@ -116,7 +143,7 @@ impl Library {
|
||||
|
||||
/// Get a pointer to function or static variable by ordinal number.
|
||||
///
|
||||
/// ## Unsafety
|
||||
/// # Safety
|
||||
///
|
||||
/// Pointer to a value of arbitrary type is returned. Using a value with wrong type is
|
||||
/// undefined.
|
||||
@@ -145,7 +172,7 @@ impl Library {
|
||||
|
||||
/// Convert a raw handle to a `Library`.
|
||||
///
|
||||
/// ## Unsafety
|
||||
/// # Safety
|
||||
///
|
||||
/// The handle shall be a result of a successful call of `LoadLibraryW` or a
|
||||
/// handle previously returned by the `Library::into_raw` call.
|
||||
@@ -255,7 +282,6 @@ struct ErrorModeGuard(DWORD);
|
||||
|
||||
impl ErrorModeGuard {
|
||||
fn new() -> Option<ErrorModeGuard> {
|
||||
const SEM_FAILCE: DWORD = 1;
|
||||
unsafe {
|
||||
if !USE_ERRORMODE.load(Ordering::Acquire) {
|
||||
let mut previous_mode = 0;
|
||||
@@ -354,7 +380,7 @@ mod tests {
|
||||
#[test]
|
||||
fn library_this_get() {
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
static VARIABLE = AtomicBool::new();
|
||||
static VARIABLE: AtomicBool = AtomicBool::new();
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn library_this_get_test_fn() {
|
||||
|
||||
Reference in New Issue
Block a user