From 6a1fbe0ab2c217740a28e6a54153fac20ca2cca7 Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Sat, 13 Apr 2013 21:40:42 -0500 Subject: initial (non-working) sketch --- .gitignore | 3 ++ dlopen.rs | 127 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 130 insertions(+) create mode 100644 .gitignore create mode 100644 dlopen.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b238204 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.so +*.o +*.a diff --git a/dlopen.rs b/dlopen.rs new file mode 100644 index 0000000..095dbde --- /dev/null +++ b/dlopen.rs @@ -0,0 +1,127 @@ +#[link(name = "dlopen", + vers = "0.0.1", + uuid = "c6a5758b-9b45-41fd-a935-f3cb7251b4eb", + url = "https://github.com/doy/rust-dlopen")]; + +#[crate_type = "lib"]; + +pub use os::Library; + +#[cfg(target_os = "linux")] +#[cfg(target_os = "android")] +#[cfg(target_os = "freebsd")] +#[cfg(target_os = "macos")] +mod os { + use core::libc::{c_char,c_int,c_void}; + + pub struct Library(*c_void); + struct Function(*c_void); + + impl Library { + pub fn open (name: &str) -> Library { + do str::as_c_str(libname(name)) |c_name| { + let lib = unsafe { dlopen(c_name, 0) }; + if lib == ptr::null() { + fail!(unsafe { str::raw::from_c_str(dlerror()) }) + } + else { + Library(lib) + } + } + } + + pub fn get_fn (&self, name: &str) -> Function { + unsafe { dlerror() }; + do str::as_c_str(name) |c_name| { + let Library(lib) = *self; + let fun = unsafe { dlsym(lib, c_name) }; + let err = unsafe { dlerror() }; + if err == ptr::null() { + fail!(unsafe { str::raw::from_c_str(err) }) + } + else { + Function(fun) + } + } + } + } + + impl Drop for Library { + fn finalize (&self) { + let Library(lib) = *self; + unsafe { dlclose(lib) }; + } + } + + impl Function { + fn call0(&self) -> A { + let Function(fun) = *self; + // XXX how do you call a c function pointer from rust? + let c_fun = unsafe { cast::transmute(fun) }; + c_fun() + } + } + + #[cfg(target_os = "linux")] + #[cfg(target_os = "android")] + #[cfg(target_os = "freebsd")] + fn libname (name: &str) -> ~str { + fmt!("lib%s.so", name) + } + + #[cfg(target_os = "macos")] + fn libname (name: &str) -> ~str { + fmt!("lib%s.dylib", name) + } + + #[link_name = "dl"] + extern "C" { + fn dlopen (filename: *c_char, flag: c_int) -> *c_void; + fn dlerror () -> *c_char; + fn dlsym (handle: *c_void, symbol: *c_char) -> *c_void; + fn dlclose (handle: *c_void) -> c_int; + } +} + +#[cfg(target_os = "win32")] +mod os { + use core::libc::{BOOL,DWORD,HMODULE,LPCTSTR}; + + struct FARPROC(*c_void); + + pub struct Library(HMODULE); + struct Function(FARPROC); + + impl Library { + pub fn open (name: &str) -> Library { + fail!(); + } + + pub fn get_fn (&self, name: &str) -> Function { + fail!(); + } + } + + impl Drop for Library { + fn finalize (&self) { + fail!(); + } + } + + impl Function { + fn call0(&self) -> A { + fail!(); + } + } + + fn libname (name: &str) -> ~str { + fmt!("%s.dll", name) + } + + extern "C" { + fn LoadLibrary(filename: LPCTSTR) -> HMODULE; + fn GetLastError() -> DWORD; + fn GetProcAddress(hModule: HMODULE, lpProcName: LPCTSTR) -> FARPROC; + fn FreeLibrary(hModule: HMODULE) -> BOOL; + } +} -- cgit v1.2.3