Skip to content

Commit

Permalink
Add try_as_raw_ptr/as_raw_ptr implementations for Symbol to convert t…
Browse files Browse the repository at this point in the history
…o raw pointer.
  • Loading branch information
AlexanderSchuetz97 committed Jul 20, 2024
1 parent 22e5251 commit f6c0d28
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 2 deletions.
6 changes: 6 additions & 0 deletions src/os/unix/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,12 @@ impl<T> Symbol<T> {
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<T> Symbol<Option<T>> {
Expand Down
8 changes: 8 additions & 0 deletions src/os/windows/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -299,6 +300,13 @@ impl<T> Symbol<T> {
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<T> Symbol<Option<T>> {
Expand Down
15 changes: 14 additions & 1 deletion src/safe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))))]
Expand Down Expand Up @@ -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<T>> {
Expand Down Expand Up @@ -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> {}
14 changes: 14 additions & 0 deletions tests/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down Expand Up @@ -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<unsafe extern "C" fn(u32) -> 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 {
Expand Down
13 changes: 12 additions & 1 deletion tests/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down Expand Up @@ -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<unsafe fn() -> *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() {
Expand Down

0 comments on commit f6c0d28

Please sign in to comment.