2015-01-29 08:19:28 +01:00
|
|
|
// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
|
2013-06-08 23:29:32 -07:00
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
2014-11-25 21:17:11 -05:00
|
|
|
//! Dynamic library facilities.
|
|
|
|
//!
|
|
|
|
//! A simple wrapper over the platform's dynamic library facilities
|
2014-04-29 11:38:51 -07:00
|
|
|
|
2015-06-09 18:15:22 -07:00
|
|
|
#![unstable(feature = "dynamic_lib",
|
|
|
|
reason = "API has not been scrutinized and is highly likely to \
|
2015-08-13 10:12:38 -07:00
|
|
|
either disappear or change",
|
|
|
|
issue = "27810")]
|
2015-11-20 16:11:20 +03:00
|
|
|
#![rustc_deprecated(since = "1.5.0", reason = "replaced with crates.io crates")]
|
2014-10-27 15:37:07 -07:00
|
|
|
#![allow(missing_docs)]
|
std: Stabilize library APIs for 1.5
This commit stabilizes and deprecates library APIs whose FCP has closed in the
last cycle, specifically:
Stabilized APIs:
* `fs::canonicalize`
* `Path::{metadata, symlink_metadata, canonicalize, read_link, read_dir, exists,
is_file, is_dir}` - all moved to inherent methods from the `PathExt` trait.
* `Formatter::fill`
* `Formatter::width`
* `Formatter::precision`
* `Formatter::sign_plus`
* `Formatter::sign_minus`
* `Formatter::alternate`
* `Formatter::sign_aware_zero_pad`
* `string::ParseError`
* `Utf8Error::valid_up_to`
* `Iterator::{cmp, partial_cmp, eq, ne, lt, le, gt, ge}`
* `<[T]>::split_{first,last}{,_mut}`
* `Condvar::wait_timeout` - note that `wait_timeout_ms` is not yet deprecated
but will be once 1.5 is released.
* `str::{R,}MatchIndices`
* `str::{r,}match_indices`
* `char::from_u32_unchecked`
* `VecDeque::insert`
* `VecDeque::shrink_to_fit`
* `VecDeque::as_slices`
* `VecDeque::as_mut_slices`
* `VecDeque::swap_remove_front` - (renamed from `swap_front_remove`)
* `VecDeque::swap_remove_back` - (renamed from `swap_back_remove`)
* `Vec::resize`
* `str::slice_mut_unchecked`
* `FileTypeExt`
* `FileTypeExt::{is_block_device, is_char_device, is_fifo, is_socket}`
* `BinaryHeap::from` - `from_vec` deprecated in favor of this
* `BinaryHeap::into_vec` - plus a `Into` impl
* `BinaryHeap::into_sorted_vec`
Deprecated APIs
* `slice::ref_slice`
* `slice::mut_ref_slice`
* `iter::{range_inclusive, RangeInclusive}`
* `std::dynamic_lib`
Closes #27706
Closes #27725
cc #27726 (align not stabilized yet)
Closes #27734
Closes #27737
Closes #27742
Closes #27743
Closes #27772
Closes #27774
Closes #27777
Closes #27781
cc #27788 (a few remaining methods though)
Closes #27790
Closes #27793
Closes #27796
Closes #27810
cc #28147 (not all parts stabilized)
2015-10-22 16:28:45 -07:00
|
|
|
#![allow(deprecated)]
|
2014-06-08 20:12:10 -07:00
|
|
|
|
2014-12-22 09:04:23 -08:00
|
|
|
use prelude::v1::*;
|
|
|
|
|
2015-03-17 13:33:26 -07:00
|
|
|
use env;
|
2015-03-30 11:00:05 -07:00
|
|
|
use ffi::{CString, OsString};
|
2015-03-23 13:42:48 -04:00
|
|
|
use path::{Path, PathBuf};
|
2013-06-08 23:29:32 -07:00
|
|
|
|
librustc: Make `Copy` opt-in.
This change makes the compiler no longer infer whether types (structures
and enumerations) implement the `Copy` trait (and thus are implicitly
copyable). Rather, you must implement `Copy` yourself via `impl Copy for
MyType {}`.
A new warning has been added, `missing_copy_implementations`, to warn
you if a non-generic public type has been added that could have
implemented `Copy` but didn't.
For convenience, you may *temporarily* opt out of this behavior by using
`#![feature(opt_out_copy)]`. Note though that this feature gate will never be
accepted and will be removed by the time that 1.0 is released, so you should
transition your code away from using it.
This breaks code like:
#[deriving(Show)]
struct Point2D {
x: int,
y: int,
}
fn main() {
let mypoint = Point2D {
x: 1,
y: 1,
};
let otherpoint = mypoint;
println!("{}{}", mypoint, otherpoint);
}
Change this code to:
#[deriving(Show)]
struct Point2D {
x: int,
y: int,
}
impl Copy for Point2D {}
fn main() {
let mypoint = Point2D {
x: 1,
y: 1,
};
let otherpoint = mypoint;
println!("{}{}", mypoint, otherpoint);
}
This is the backwards-incompatible part of #13231.
Part of RFC #3.
[breaking-change]
2014-12-05 17:01:33 -08:00
|
|
|
pub struct DynamicLibrary {
|
|
|
|
handle: *mut u8
|
|
|
|
}
|
2013-06-08 23:29:32 -07:00
|
|
|
|
|
|
|
impl Drop for DynamicLibrary {
|
2013-09-16 21:18:07 -04:00
|
|
|
fn drop(&mut self) {
|
2013-11-20 14:17:12 -08:00
|
|
|
match dl::check_for_errors_in(|| {
|
2013-06-08 23:29:32 -07:00
|
|
|
unsafe {
|
|
|
|
dl::close(self.handle)
|
|
|
|
}
|
2013-11-20 14:17:12 -08:00
|
|
|
}) {
|
2013-08-01 14:58:37 -07:00
|
|
|
Ok(()) => {},
|
2014-10-09 15:17:22 -04:00
|
|
|
Err(str) => panic!("{}", str)
|
2013-06-08 23:29:32 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl DynamicLibrary {
|
|
|
|
/// Lazily open a dynamic library. When passed None it gives a
|
|
|
|
/// handle to the calling process
|
2014-11-25 13:28:35 -08:00
|
|
|
pub fn open(filename: Option<&Path>) -> Result<DynamicLibrary, String> {
|
2015-03-23 13:42:48 -04:00
|
|
|
let maybe_library = dl::open(filename.map(|path| path.as_os_str()));
|
2015-01-10 22:53:22 +09:00
|
|
|
|
|
|
|
// The dynamic library must not be constructed if there is
|
|
|
|
// an error opening the library so the destructor does not
|
|
|
|
// run.
|
|
|
|
match maybe_library {
|
|
|
|
Err(err) => Err(err),
|
|
|
|
Ok(handle) => Ok(DynamicLibrary { handle: handle })
|
2013-06-08 23:29:32 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-15 19:28:46 +02:00
|
|
|
/// Prepends a path to this process's search path for dynamic libraries
|
|
|
|
pub fn prepend_search_path(path: &Path) {
|
|
|
|
let mut search_path = DynamicLibrary::search_path();
|
2015-03-23 13:42:48 -04:00
|
|
|
search_path.insert(0, path.to_path_buf());
|
|
|
|
env::set_var(DynamicLibrary::envvar(), &DynamicLibrary::create_path(&search_path));
|
2014-05-15 19:28:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/// From a slice of paths, create a new vector which is suitable to be an
|
|
|
|
/// environment variable for this platforms dylib search path.
|
2015-03-23 13:42:48 -04:00
|
|
|
pub fn create_path(path: &[PathBuf]) -> OsString {
|
|
|
|
let mut newvar = OsString::new();
|
2014-05-15 19:28:46 +02:00
|
|
|
for (i, path) in path.iter().enumerate() {
|
|
|
|
if i > 0 { newvar.push(DynamicLibrary::separator()); }
|
2015-03-23 13:42:48 -04:00
|
|
|
newvar.push(path);
|
2014-05-15 19:28:46 +02:00
|
|
|
}
|
|
|
|
return newvar;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the environment variable for this process's dynamic library
|
|
|
|
/// search path
|
|
|
|
pub fn envvar() -> &'static str {
|
|
|
|
if cfg!(windows) {
|
|
|
|
"PATH"
|
2014-04-29 11:38:51 -07:00
|
|
|
} else if cfg!(target_os = "macos") {
|
2014-05-15 19:28:46 +02:00
|
|
|
"DYLD_LIBRARY_PATH"
|
2014-04-29 11:38:51 -07:00
|
|
|
} else {
|
2014-05-15 19:28:46 +02:00
|
|
|
"LD_LIBRARY_PATH"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-23 13:42:48 -04:00
|
|
|
fn separator() -> &'static str {
|
|
|
|
if cfg!(windows) { ";" } else { ":" }
|
2014-05-15 19:28:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the current search path for dynamic libraries being used by this
|
|
|
|
/// process
|
2015-03-23 13:42:48 -04:00
|
|
|
pub fn search_path() -> Vec<PathBuf> {
|
2015-02-11 11:47:53 -08:00
|
|
|
match env::var_os(DynamicLibrary::envvar()) {
|
2015-03-23 13:42:48 -04:00
|
|
|
Some(var) => env::split_paths(&var).collect(),
|
2015-01-27 12:20:58 -08:00
|
|
|
None => Vec::new(),
|
2014-05-08 23:33:22 +10:00
|
|
|
}
|
2014-04-29 11:38:51 -07:00
|
|
|
}
|
|
|
|
|
2015-04-13 10:21:32 -04:00
|
|
|
/// Accesses the value at the symbol of the dynamic library.
|
2014-06-25 12:47:34 -07:00
|
|
|
pub unsafe fn symbol<T>(&self, symbol: &str) -> Result<*mut T, String> {
|
2013-12-09 23:16:18 -08:00
|
|
|
// This function should have a lifetime constraint of 'a on
|
2013-06-08 23:29:32 -07:00
|
|
|
// T but that feature is still unimplemented
|
|
|
|
|
2015-02-17 22:47:40 -08:00
|
|
|
let raw_string = CString::new(symbol).unwrap();
|
2013-11-20 14:17:12 -08:00
|
|
|
let maybe_symbol_value = dl::check_for_errors_in(|| {
|
2014-11-25 13:28:35 -08:00
|
|
|
dl::symbol(self.handle, raw_string.as_ptr())
|
2013-11-20 14:17:12 -08:00
|
|
|
});
|
2013-06-08 23:29:32 -07:00
|
|
|
|
2013-08-01 14:58:37 -07:00
|
|
|
// The value must not be constructed if there is an error so
|
|
|
|
// the destructor does not run.
|
|
|
|
match maybe_symbol_value {
|
|
|
|
Err(err) => Err(err),
|
2015-10-17 20:15:26 -04:00
|
|
|
Ok(symbol_value) => Ok(symbol_value as *mut T)
|
2013-06-08 23:29:32 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-24 20:51:34 -05:00
|
|
|
#[cfg(all(test, not(target_os = "ios"), not(target_os = "nacl")))]
|
2015-04-24 17:30:41 +02:00
|
|
|
mod tests {
|
2013-08-01 14:58:37 -07:00
|
|
|
use super::*;
|
2014-12-22 09:04:23 -08:00
|
|
|
use prelude::v1::*;
|
2013-08-01 14:58:37 -07:00
|
|
|
use libc;
|
2014-06-12 21:34:32 -07:00
|
|
|
use mem;
|
2015-03-23 13:42:48 -04:00
|
|
|
use path::Path;
|
2013-08-01 14:58:37 -07:00
|
|
|
|
|
|
|
#[test]
|
2015-04-21 15:56:55 -07:00
|
|
|
#[cfg_attr(any(windows,
|
|
|
|
target_os = "android", // FIXME #10379
|
|
|
|
target_env = "musl"), ignore)]
|
2013-08-01 14:58:37 -07:00
|
|
|
fn test_loading_cosine() {
|
|
|
|
// The math library does not need to be loaded since it is already
|
|
|
|
// statically linked in
|
2015-03-17 13:33:26 -07:00
|
|
|
let libm = match DynamicLibrary::open(None) {
|
2014-10-09 15:17:22 -04:00
|
|
|
Err(error) => panic!("Could not load self as module: {}", error),
|
2013-08-01 14:58:37 -07:00
|
|
|
Ok(libm) => libm
|
|
|
|
};
|
|
|
|
|
|
|
|
let cosine: extern fn(libc::c_double) -> libc::c_double = unsafe {
|
|
|
|
match libm.symbol("cos") {
|
2014-10-09 15:17:22 -04:00
|
|
|
Err(error) => panic!("Could not load function cos: {}", error),
|
2014-06-25 12:47:34 -07:00
|
|
|
Ok(cosine) => mem::transmute::<*mut u8, _>(cosine)
|
2013-08-01 14:58:37 -07:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
let argument = 0.0;
|
|
|
|
let expected_result = 1.0;
|
|
|
|
let result = cosine(argument);
|
|
|
|
if result != expected_result {
|
2014-10-09 15:17:22 -04:00
|
|
|
panic!("cos({}) != {} but equaled {} instead", argument,
|
2013-10-03 21:34:35 -07:00
|
|
|
expected_result, result)
|
2013-08-01 14:58:37 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2014-09-28 22:31:50 -07:00
|
|
|
#[cfg(any(target_os = "linux",
|
|
|
|
target_os = "macos",
|
|
|
|
target_os = "freebsd",
|
2015-01-29 08:19:28 +01:00
|
|
|
target_os = "dragonfly",
|
2015-01-16 23:51:04 -08:00
|
|
|
target_os = "bitrig",
|
2015-06-30 20:37:11 -07:00
|
|
|
target_os = "netbsd",
|
2015-01-29 08:19:28 +01:00
|
|
|
target_os = "openbsd"))]
|
2013-08-01 14:58:37 -07:00
|
|
|
fn test_errors_do_not_crash() {
|
|
|
|
// Open /dev/null as a library to get an error, and make sure
|
|
|
|
// that only causes an error, and not a crash.
|
2014-05-05 14:53:57 -07:00
|
|
|
let path = Path::new("/dev/null");
|
2013-08-01 14:58:37 -07:00
|
|
|
match DynamicLibrary::open(Some(&path)) {
|
|
|
|
Err(_) => {}
|
2014-10-09 15:17:22 -04:00
|
|
|
Ok(_) => panic!("Successfully opened the empty library.")
|
2013-06-08 23:29:32 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-28 22:31:50 -07:00
|
|
|
#[cfg(any(target_os = "linux",
|
|
|
|
target_os = "android",
|
|
|
|
target_os = "macos",
|
|
|
|
target_os = "ios",
|
|
|
|
target_os = "freebsd",
|
2015-01-29 08:19:28 +01:00
|
|
|
target_os = "dragonfly",
|
2015-01-16 23:51:04 -08:00
|
|
|
target_os = "bitrig",
|
2015-06-30 20:37:11 -07:00
|
|
|
target_os = "netbsd",
|
2015-01-29 08:19:28 +01:00
|
|
|
target_os = "openbsd"))]
|
2015-01-10 22:53:22 +09:00
|
|
|
mod dl {
|
2014-12-22 09:04:23 -08:00
|
|
|
use prelude::v1::*;
|
2014-11-25 13:28:35 -08:00
|
|
|
|
2015-03-23 13:42:48 -04:00
|
|
|
use ffi::{CStr, OsStr};
|
2014-11-25 13:28:35 -08:00
|
|
|
use str;
|
2013-06-08 23:29:32 -07:00
|
|
|
use libc;
|
|
|
|
use ptr;
|
|
|
|
|
2015-03-23 13:42:48 -04:00
|
|
|
pub fn open(filename: Option<&OsStr>) -> Result<*mut u8, String> {
|
2015-01-10 22:53:22 +09:00
|
|
|
check_for_errors_in(|| {
|
|
|
|
unsafe {
|
|
|
|
match filename {
|
|
|
|
Some(filename) => open_external(filename),
|
|
|
|
None => open_internal(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
const LAZY: libc::c_int = 1;
|
|
|
|
|
2015-03-23 13:42:48 -04:00
|
|
|
unsafe fn open_external(filename: &OsStr) -> *mut u8 {
|
|
|
|
let s = filename.to_cstring().unwrap();
|
2015-11-02 16:23:22 -08:00
|
|
|
libc::dlopen(s.as_ptr(), LAZY) as *mut u8
|
2013-06-15 10:10:49 +02:00
|
|
|
}
|
|
|
|
|
2015-01-10 22:53:22 +09:00
|
|
|
unsafe fn open_internal() -> *mut u8 {
|
2015-11-02 16:23:22 -08:00
|
|
|
libc::dlopen(ptr::null(), LAZY) as *mut u8
|
2013-06-08 23:29:32 -07:00
|
|
|
}
|
|
|
|
|
2014-12-07 14:15:25 -05:00
|
|
|
pub fn check_for_errors_in<T, F>(f: F) -> Result<T, String> where
|
|
|
|
F: FnOnce() -> T,
|
|
|
|
{
|
2015-05-27 11:18:36 +03:00
|
|
|
use sync::StaticMutex;
|
|
|
|
static LOCK: StaticMutex = StaticMutex::new();
|
2013-06-08 23:29:32 -07:00
|
|
|
unsafe {
|
2013-10-03 21:34:35 -07:00
|
|
|
// dlerror isn't thread safe, so we need to lock around this entire
|
2013-12-12 17:27:37 -08:00
|
|
|
// sequence
|
2014-10-10 21:59:10 -07:00
|
|
|
let _guard = LOCK.lock();
|
2015-11-02 16:23:22 -08:00
|
|
|
let _old_error = libc::dlerror();
|
2013-12-05 17:34:37 -08:00
|
|
|
|
|
|
|
let result = f();
|
|
|
|
|
2015-11-02 16:23:22 -08:00
|
|
|
let last_error = libc::dlerror() as *const _;
|
2013-12-05 17:34:37 -08:00
|
|
|
let ret = if ptr::null() == last_error {
|
|
|
|
Ok(result)
|
|
|
|
} else {
|
2015-02-17 22:47:40 -08:00
|
|
|
let s = CStr::from_ptr(last_error).to_bytes();
|
2015-09-08 00:36:29 +02:00
|
|
|
Err(str::from_utf8(s).unwrap().to_owned())
|
2013-12-05 17:34:37 -08:00
|
|
|
};
|
2014-02-13 17:17:50 +11:00
|
|
|
|
2013-12-05 17:34:37 -08:00
|
|
|
ret
|
2013-06-08 23:29:32 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-25 12:47:34 -07:00
|
|
|
pub unsafe fn symbol(handle: *mut u8,
|
|
|
|
symbol: *const libc::c_char) -> *mut u8 {
|
2015-11-02 16:23:22 -08:00
|
|
|
libc::dlsym(handle as *mut libc::c_void, symbol) as *mut u8
|
2013-06-08 23:29:32 -07:00
|
|
|
}
|
2014-06-25 12:47:34 -07:00
|
|
|
pub unsafe fn close(handle: *mut u8) {
|
2015-11-02 16:23:22 -08:00
|
|
|
libc::dlclose(handle as *mut libc::c_void); ()
|
2015-01-29 08:19:28 +01:00
|
|
|
}
|
2013-06-08 23:29:32 -07:00
|
|
|
}
|
|
|
|
|
2014-08-10 21:26:45 -07:00
|
|
|
#[cfg(target_os = "windows")]
|
2015-01-10 22:53:22 +09:00
|
|
|
mod dl {
|
2015-04-21 15:59:14 -07:00
|
|
|
use prelude::v1::*;
|
|
|
|
|
2015-03-23 13:42:48 -04:00
|
|
|
use ffi::OsStr;
|
2013-06-08 23:29:32 -07:00
|
|
|
use libc;
|
2015-03-23 13:42:48 -04:00
|
|
|
use os::windows::prelude::*;
|
2013-06-15 10:10:49 +02:00
|
|
|
use ptr;
|
2015-11-02 16:23:22 -08:00
|
|
|
use sys::c;
|
|
|
|
use sys::os;
|
2015-01-10 22:53:22 +09:00
|
|
|
|
2015-03-23 13:42:48 -04:00
|
|
|
pub fn open(filename: Option<&OsStr>) -> Result<*mut u8, String> {
|
2015-01-10 22:53:22 +09:00
|
|
|
// disable "dll load failed" error dialog.
|
|
|
|
let mut use_thread_mode = true;
|
|
|
|
let prev_error_mode = unsafe {
|
|
|
|
// SEM_FAILCRITICALERRORS 0x01
|
|
|
|
let new_error_mode = 1;
|
|
|
|
let mut prev_error_mode = 0;
|
|
|
|
// Windows >= 7 supports thread error mode.
|
2015-11-02 16:23:22 -08:00
|
|
|
let result = c::SetThreadErrorMode(new_error_mode,
|
|
|
|
&mut prev_error_mode);
|
2015-01-10 22:53:22 +09:00
|
|
|
if result == 0 {
|
|
|
|
let err = os::errno();
|
2015-11-02 16:23:22 -08:00
|
|
|
if err == c::ERROR_CALL_NOT_IMPLEMENTED as i32 {
|
2015-01-10 22:53:22 +09:00
|
|
|
use_thread_mode = false;
|
2015-03-18 09:36:18 -07:00
|
|
|
// SetThreadErrorMode not found. use fallback solution:
|
|
|
|
// SetErrorMode() Note that SetErrorMode is process-wide so
|
|
|
|
// this can cause race condition! However, since even
|
|
|
|
// Windows APIs do not care of such problem (#20650), we
|
|
|
|
// just assume SetErrorMode race is not a great deal.
|
2015-11-02 16:23:22 -08:00
|
|
|
prev_error_mode = c::SetErrorMode(new_error_mode);
|
2015-01-10 22:53:22 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
prev_error_mode
|
|
|
|
};
|
2013-06-08 23:29:32 -07:00
|
|
|
|
2015-01-10 22:53:22 +09:00
|
|
|
unsafe {
|
2015-11-02 16:23:22 -08:00
|
|
|
c::SetLastError(0);
|
2015-01-10 22:53:22 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
let result = match filename {
|
|
|
|
Some(filename) => {
|
2015-03-23 13:42:48 -04:00
|
|
|
let filename_str: Vec<_> =
|
2015-06-10 17:22:20 +01:00
|
|
|
filename.encode_wide().chain(Some(0)).collect();
|
2015-01-10 22:53:22 +09:00
|
|
|
let result = unsafe {
|
2015-11-02 16:23:22 -08:00
|
|
|
c::LoadLibraryW(filename_str.as_ptr())
|
2015-01-10 22:53:22 +09:00
|
|
|
};
|
|
|
|
// beware: Vec/String may change errno during drop!
|
|
|
|
// so we get error here.
|
|
|
|
if result == ptr::null_mut() {
|
|
|
|
let errno = os::errno();
|
|
|
|
Err(os::error_string(errno))
|
|
|
|
} else {
|
|
|
|
Ok(result as *mut u8)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None => {
|
|
|
|
let mut handle = ptr::null_mut();
|
|
|
|
let succeeded = unsafe {
|
2015-11-02 16:23:22 -08:00
|
|
|
c::GetModuleHandleExW(0 as c::DWORD, ptr::null(),
|
|
|
|
&mut handle)
|
2015-01-10 22:53:22 +09:00
|
|
|
};
|
2015-11-02 16:23:22 -08:00
|
|
|
if succeeded == c::FALSE {
|
2015-01-10 22:53:22 +09:00
|
|
|
let errno = os::errno();
|
|
|
|
Err(os::error_string(errno))
|
|
|
|
} else {
|
|
|
|
Ok(handle as *mut u8)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
if use_thread_mode {
|
2015-11-02 16:23:22 -08:00
|
|
|
c::SetThreadErrorMode(prev_error_mode, ptr::null_mut());
|
2015-01-10 22:53:22 +09:00
|
|
|
} else {
|
2015-11-02 16:23:22 -08:00
|
|
|
c::SetErrorMode(prev_error_mode);
|
2015-01-10 22:53:22 +09:00
|
|
|
}
|
|
|
|
}
|
2013-06-15 10:10:49 +02:00
|
|
|
|
2015-01-10 22:53:22 +09:00
|
|
|
result
|
2013-06-08 23:29:32 -07:00
|
|
|
}
|
|
|
|
|
2014-12-07 14:15:25 -05:00
|
|
|
pub fn check_for_errors_in<T, F>(f: F) -> Result<T, String> where
|
|
|
|
F: FnOnce() -> T,
|
|
|
|
{
|
2013-06-08 23:29:32 -07:00
|
|
|
unsafe {
|
2015-11-02 16:23:22 -08:00
|
|
|
c::SetLastError(0);
|
2013-06-08 23:29:32 -07:00
|
|
|
|
2013-12-05 17:34:37 -08:00
|
|
|
let result = f();
|
2013-06-08 23:29:32 -07:00
|
|
|
|
2013-12-05 17:34:37 -08:00
|
|
|
let error = os::errno();
|
|
|
|
if 0 == error {
|
|
|
|
Ok(result)
|
|
|
|
} else {
|
|
|
|
Err(format!("Error code {}", error))
|
|
|
|
}
|
2013-06-08 23:29:32 -07:00
|
|
|
}
|
|
|
|
}
|
2013-10-03 21:34:35 -07:00
|
|
|
|
2014-06-25 12:47:34 -07:00
|
|
|
pub unsafe fn symbol(handle: *mut u8, symbol: *const libc::c_char) -> *mut u8 {
|
2015-11-02 16:23:22 -08:00
|
|
|
c::GetProcAddress(handle as c::HMODULE, symbol) as *mut u8
|
2013-06-08 23:29:32 -07:00
|
|
|
}
|
2014-06-25 12:47:34 -07:00
|
|
|
pub unsafe fn close(handle: *mut u8) {
|
2015-11-02 16:23:22 -08:00
|
|
|
c::FreeLibrary(handle as c::HMODULE);
|
2013-08-12 15:27:46 +09:00
|
|
|
}
|
2013-06-08 23:29:32 -07:00
|
|
|
}
|
2015-10-24 20:51:34 -05:00
|
|
|
|
|
|
|
#[cfg(target_os = "nacl")]
|
|
|
|
pub mod dl {
|
|
|
|
use ffi::OsStr;
|
|
|
|
use ptr;
|
|
|
|
use result::Result;
|
|
|
|
use result::Result::Err;
|
|
|
|
use libc;
|
|
|
|
use string::String;
|
|
|
|
use ops::FnOnce;
|
|
|
|
use option::Option;
|
|
|
|
|
|
|
|
pub fn open(_filename: Option<&OsStr>) -> Result<*mut u8, String> {
|
|
|
|
Err(format!("NaCl + Newlib doesn't impl loading shared objects"))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn check_for_errors_in<T, F>(_f: F) -> Result<T, String>
|
|
|
|
where F: FnOnce() -> T,
|
|
|
|
{
|
|
|
|
Err(format!("NaCl doesn't support shared objects"))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub unsafe fn symbol(_handle: *mut u8, _symbol: *const libc::c_char) -> *mut u8 {
|
|
|
|
ptr::null_mut()
|
|
|
|
}
|
|
|
|
pub unsafe fn close(_handle: *mut u8) { }
|
|
|
|
}
|