我目前正在使用 Rust 来使用
dlfcn.h
中定义的 POSIX 函数,目的是在单独的 .so
文件中调用函数。
该项目实际上包含 2 个板条箱:
动态库有4行长,代码如下:
#[no_mangle]
pub extern "Rust" fn hello_world() -> String {
String::from("Hello World !")
}
但是可执行二进制文件有点复杂,看起来像这样:
#![feature(str_from_raw_parts)]
fn open_dl(path: &str) -> Result<*mut libc::c_void, String> {
let path = format!("{path}\0");
let path: *const libc::c_char = unsafe { std::mem::transmute(path.as_ptr()) };
let handle = unsafe { libc::dlopen(path, libc::RTLD_NOW) };
if handle.is_null() {
let dl_error: &str = unsafe {
let ptr = libc::dlerror();
let len = libc::strlen(ptr);
std::str::from_raw_parts(std::mem::transmute(ptr), len)
};
return Err(String::from(dl_error));
}
Ok(handle)
}
fn get_symbol<T>(handle: *mut libc::c_void, symbol: &str) -> Result<&T, String> {
let symbol_name = format!("{symbol}\0");
let symbol = unsafe { libc::dlsym(handle, std::mem::transmute(symbol_name.as_ptr())) };
if symbol.is_null() {
let dl_error: &str = unsafe {
let ptr = libc::dlerror();
let len = libc::strlen(ptr);
std::str::from_raw_parts(std::mem::transmute(ptr), len)
};
return Err(String::from(dl_error));
}
return unsafe { Ok(std::mem::transmute(symbol)) };
}
fn main() -> Result<(), String> {
let handle = open_dl("./libfoo.so")?;
// Tricky part, get the symbol with the correct signature and calling it
let symbol: &fn() -> String = get_symbol(handle, "hello_world")?;
let val = symbol(); // Blows up
println!("{val}");
Ok(())
}
我的问题是 get_symbol 似乎工作正常,获得的指针不为空,所以我希望调用它后面的函数不会导致任何问题,但是当我尝试这样做时,我得到了 SEGFAULT。你想知道为什么它会发生SEGFAULT吗?
get_symbol
的返回类型错误。
dlsym
返回 *mut c_void
(在函数指针的情况下)内部包含 Option<extern "C" fn(...)>
。
您必须将返回值直接转换为 Option,而不是引用。
请记住,在 Rust 中函数指针并不暗示指针语义,更不用说引用语义了。