From 2bdb7f95729461c3fba2e0ae6595b636df4ccbe6 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Fri, 11 Oct 2024 18:28:39 -0500 Subject: support loading lib from /lib or same dir as bin and resolve 2 clippy issues need to test on other platforms gestured-towards here in lib.rs --- impls/monero.rs/README.md | 4 +-- impls/monero.rs/build.rs | 2 +- impls/monero.rs/src/lib.rs | 74 +++++++++++++++++++++++++++++++++++----------- 3 files changed, 60 insertions(+), 20 deletions(-) (limited to 'impls') diff --git a/impls/monero.rs/README.md b/impls/monero.rs/README.md index fbac577..422f7b9 100644 --- a/impls/monero.rs/README.md +++ b/impls/monero.rs/README.md @@ -42,5 +42,5 @@ cargo run ``` ## Using `monero_rust` in your own crate -Refer to the `example` folder. `libwallet2_api_c.so` must be in the same -directory as the binary (*eg.* at `example/target/debug/libwallet2_api_c.so`). +Refer to the `example` folder. `libwallet2_api_c.so` must be in `lib/` or in +the same directory as the binary (*eg.* in `example/target/debug/`). diff --git a/impls/monero.rs/build.rs b/impls/monero.rs/build.rs index 59e87d9..357028b 100644 --- a/impls/monero.rs/build.rs +++ b/impls/monero.rs/build.rs @@ -40,6 +40,6 @@ fn main() { .join("src") .join("bindings.rs"); bindings - .write_to_file(&out_path) + .write_to_file(out_path) .expect("Couldn't write bindings!"); } diff --git a/impls/monero.rs/src/lib.rs b/impls/monero.rs/src/lib.rs index 2175083..28b7ddb 100644 --- a/impls/monero.rs/src/lib.rs +++ b/impls/monero.rs/src/lib.rs @@ -1,5 +1,6 @@ use std::ffi::{CStr, CString}; use std::os::raw::{c_char, c_int, c_void}; +use std::path::PathBuf; use std::ptr::NonNull; use std::sync::Arc; @@ -24,34 +25,72 @@ pub struct WalletManager { library: Arc, } +#[cfg(target_os = "windows")] +const LIB_NAME: &str = "wallet2_api_c.dll"; +#[cfg(target_os = "linux")] +const LIB_NAME: &str = "libwallet2_api_c.so"; +#[cfg(target_os = "macos")] +const LIB_NAME: &str = "libwallet2_api_c.dylib"; + impl WalletManager { /// Create a new WalletManager, optionally specifying the path to the shared library. pub fn new(lib_path: Option<&str>) -> WalletResult { let lib = match lib_path { - Some(path) => { - unsafe { - Library::new(path).map_err(|e| WalletError::LibraryLoadError(e.to_string()))? - } - } + Some(path) => unsafe { + Library::new(path).map_err(|e| WalletError::LibraryLoadError(e.to_string()))? + }, None => { - // Attempt to load from the same directory as the executable. + // Attempt to load from multiple candidate paths. let exe_path = std::env::current_exe() .map_err(|e| WalletError::LibraryLoadError(e.to_string()))?; let exe_dir = exe_path.parent().ok_or_else(|| { WalletError::LibraryLoadError("Failed to get executable directory".to_string()) })?; - let lib_path = exe_dir.join("libwallet2_api_c.so"); - - unsafe { - if lib_path.exists() { - Library::new(lib_path) - .map_err(|e| WalletError::LibraryLoadError(e.to_string()))? - } else { - // Fallback to standard locations. - Library::new("libwallet2_api_c.so") - .map_err(|e| WalletError::LibraryLoadError(e.to_string()))? + + // Prepare the list of candidate paths. + let mut candidates: Vec = Vec::new(); + + // Candidate 1: ../../lib/libwallet2_api_c.so relative to the executable. + if let Some(lib_dir) = exe_dir.parent().and_then(|p| p.parent()) { + let lib_path = lib_dir.join("lib").join(LIB_NAME); + candidates.push(lib_path); + } + + // Candidate 2: libwallet2_api_c.so in the same directory as the executable. + candidates.push(exe_dir.join(LIB_NAME)); + + // Candidate 3: Let the library loader search standard library paths. + // We represent this by using the library name directly. + candidates.push(PathBuf::from(LIB_NAME)); + + // Try to load the library from the candidate paths. + let mut library = None; + for candidate in &candidates { + let result = unsafe { Library::new(candidate) }; + match result { + Ok(lib) => { + library = Some(lib); + break; + } + Err(err) => { + eprintln!( + "Failed to load library from {}: {}", + candidate.display(), + err + ); + continue; // Try next candidate. + } } } + + // If none of the candidates worked, return an error. + library.ok_or_else(|| { + WalletError::LibraryLoadError(format!( + "Failed to load {} from paths: {:?}", + LIB_NAME, + candidates + )) + })? } }; @@ -59,7 +98,8 @@ impl WalletManager { unsafe { let func: Symbol *mut c_void> = - library.get(b"MONERO_WalletManagerFactory_getWalletManager\0") + library + .get(b"MONERO_WalletManagerFactory_getWalletManager\0") .map_err(|e| WalletError::LibraryLoadError(e.to_string()))?; let ptr = func(); NonNull::new(ptr) -- cgit v1.2.3