From f6c0d28c7de084ae21da282ba851220b07414bb2 Mon Sep 17 00:00:00 2001 From: Alexander Schuetz Date: Sat, 20 Jul 2024 11:32:03 +0200 Subject: [PATCH] Add try_as_raw_ptr/as_raw_ptr implementations for Symbol to convert to raw pointer. --- src/os/unix/mod.rs | 6 ++++++ src/os/windows/mod.rs | 8 ++++++++ src/safe.rs | 15 ++++++++++++++- tests/functions.rs | 14 ++++++++++++++ tests/windows.rs | 13 ++++++++++++- 5 files changed, 54 insertions(+), 2 deletions(-) diff --git a/src/os/unix/mod.rs b/src/os/unix/mod.rs index 6347e0270..202a002f1 100644 --- a/src/os/unix/mod.rs +++ b/src/os/unix/mod.rs @@ -396,6 +396,12 @@ impl Symbol { pub fn into_raw(self) -> *mut raw::c_void { self.pointer } + + /// Convert the loaded `Symbol` into a raw pointer. + /// For unix this does the same as into_raw. + pub fn as_raw_ptr(self) -> *mut raw::c_void { + return self.pointer + } } impl Symbol> { diff --git a/src/os/windows/mod.rs b/src/os/windows/mod.rs index 172801e16..cc0373c36 100644 --- a/src/os/windows/mod.rs +++ b/src/os/windows/mod.rs @@ -19,6 +19,7 @@ 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::raw; /// The platform-specific counterpart of the cross-platform [`Library`](crate::Library). pub struct Library(HMODULE); @@ -299,6 +300,13 @@ impl Symbol { pub fn into_raw(self) -> FARPROC { self.pointer } + + /// Convert the loaded `Symbol` into a raw pointer. + pub fn as_raw_ptr(self) -> *mut raw::c_void { + return self.pointer + .map(|raw| raw as *mut raw::c_void) + .unwrap_or(std::ptr::null_mut()) + } } impl Symbol> { diff --git a/src/safe.rs b/src/safe.rs index 49be0cfc9..b48272582 100644 --- a/src/safe.rs +++ b/src/safe.rs @@ -9,6 +9,7 @@ use std::ffi::OsStr; use std::fmt; use std::marker; use std::ops; +use std::os::raw; /// A loaded dynamic library. #[cfg_attr(libloading_docs, doc(cfg(any(unix, windows))))] @@ -249,6 +250,18 @@ impl<'lib, T> Symbol<'lib, T> { pd: marker::PhantomData, } } + + /// Try to convert the symbol into a raw pointer. + /// Success depends on the platform. Currently, this fn always succeeds and returns some. + /// + /// # Safety + /// + /// Using this function relinquishes all the lifetime guarantees. It is up to the developer to + /// ensure the resulting `Symbol` is not used past the lifetime of the `Library` this symbol + /// was loaded from. + pub unsafe fn try_as_raw_ptr(self) -> Option<*mut raw::c_void> { + return Some(unsafe{self.into_raw()}.as_raw_ptr()); + } } impl<'lib, T> Symbol<'lib, Option> { @@ -296,4 +309,4 @@ impl<'lib, T> fmt::Debug for Symbol<'lib, T> { } unsafe impl<'lib, T: Send> Send for Symbol<'lib, T> {} -unsafe impl<'lib, T: Sync> Sync for Symbol<'lib, T> {} +unsafe impl<'lib, T: Sync> Sync for Symbol<'lib, T> {} \ No newline at end of file diff --git a/tests/functions.rs b/tests/functions.rs index a0175a674..b9c9ac315 100644 --- a/tests/functions.rs +++ b/tests/functions.rs @@ -2,6 +2,7 @@ extern crate windows_sys; extern crate libloading; +use std::os::raw::c_void; use libloading::{Library, Symbol}; const TARGET_DIR: Option<&'static str> = option_env!("CARGO_TARGET_DIR"); @@ -44,6 +45,19 @@ fn test_id_u32() { } } +#[test] +fn test_try_into_ptr() { + make_helpers(); + unsafe { + let lib = Library::new(lib_path()).unwrap(); + let f: Symbol u32> = lib.get(b"test_identity_u32\0").unwrap(); + let ptr: *mut c_void = f.try_as_raw_ptr().unwrap(); + assert!(!ptr.is_null()); + let ptr_casted : extern "C" fn(u32) -> u32 = std::mem::transmute(ptr); + assert_eq!(42, ptr_casted(42)); + } +} + #[repr(C)] #[derive(Clone, Copy, PartialEq, Debug)] struct S { diff --git a/tests/windows.rs b/tests/windows.rs index b4aad4a69..c898f18f4 100644 --- a/tests/windows.rs +++ b/tests/windows.rs @@ -2,7 +2,7 @@ extern crate libloading; use libloading::os::windows::*; use std::ffi::CStr; - +use std::os::raw::c_void; // The ordinal DLL contains exactly one function (other than DllMain, that is) with ordinal number // 1. This function has the sugnature `fn() -> *const c_char` and returns a string "bunny\0" (in // reference to WindowsBunny). @@ -37,6 +37,17 @@ fn test_ordinal() { } } +#[cfg(any(target_arch="x86", target_arch="x86_64"))] +#[test] +fn test_try_into_ptr() { + let lib = load_ordinal_lib(); + unsafe { + let windows: Symbol *const i8> = lib.get_ordinal(1).expect("function"); + let ptr : *mut c_void = windows.as_raw_ptr(); + assert!(!ptr.is_null()); + } +} + #[cfg(any(target_arch="x86", target_arch="x86_64"))] #[test] fn test_ordinal_missing_fails() {