互联网的大家好,
我正在努力调用存储在libc::c_void
-Pointer中的函数。我不能告诉Rust指针是可调用的,我也不知道该怎么做。
我想翻译此C ++代码
void * malloc(size_t size) {
static void *(*real_malloc)(size_t) = nullptr;
if (real_malloc == nullptr) {
real_malloc = reinterpret_cast<void *(*)(size_t)> (dlsym(RTLD_NEXT, "malloc"));
}
// do some logging stuff
void * ptr = real_malloc(size);
return ptr;
}
到Rust。
#[no_mangle]
pub extern fn malloc(bytes: usize) {
let c_string = "malloc\0".as_mut_ptr() as *mut i8; // char array for libc
let real_malloc: *mut libc::c_void = libc::dlsym(libc::RTLD_NEXT, c_string);
return real_malloc(bytes);
}
到目前为止,这是我在互联网上搜索并尝试1小时后的进步。我是Rust的新手,还不熟悉Rust / FFI / libc的Rust。我对不安全的{}进行了很多尝试,对as
进行了强制转换,但始终遇到以下问题:
return real_malloc(bytes);
^^^^^^^^^^^^^^^^^^ expected (), found *-ptr
问题1:我如何调用存储在real_malloc
中的void指针后面的函数?
第二季度:这样,我的Rust-String到C-String转换可行吗?
答案 0 :(得分:0)
我知道了!也许有更好的方法,但是它行得通。
诀窍是用std::mem::transmute
将void指针“投射”到c-function-Type,因为它不能与as
一起使用
type LibCMallocT = fn(usize) -> *mut libc::c_void;
// C-Style string for symbol-name
let c_string = "malloc\0".as_ptr() as *mut i8; // char array for libc
// Void-Pointer to address of symbol
let real_malloc_addr: *mut libc::c_void = unsafe {libc::dlsym(libc::RTLD_NEXT, c_string)};
// transmute: "Reinterprets the bits of a value of one type as another type"
// Transform void-pointer-type to callable C-Function
let real_malloc: LibCMallocT = unsafe { std::mem::transmute(real_malloc_addr) }
构建共享库时,可以验证其是否像这样工作:
LD_PRELOAD=./target/debug/libmalloc_log_lib.so some-binary
我的完整代码:
extern crate libc;
use std::io::Write;
const MSG: &str = "HELLO WORLD\n";
type LibCMallocT = fn(usize) -> *mut libc::c_void;
#[no_mangle] // then "malloc" is the symbol name so that ELF-Files can find it (if this lib is preloaded)
pub extern fn malloc(bytes: usize) -> *mut libc::c_void {
/// Disable logging aka return immediately the pointer from the real malloc (libc malloc)
static mut RETURN_IMMEDIATELY: bool = false;
// C-Style string for symbol-name
let c_string = "malloc\0".as_ptr() as *mut i8; // char array for libc
// Void-Pointer to address of symbol
let real_malloc_addr: *mut libc::c_void = unsafe {libc::dlsym(libc::RTLD_NEXT, c_string)};
// transmute: "Reinterprets the bits of a value of one type as another type"
// Transform void-pointer-type to callable C-Function
let real_malloc: LibCMallocT = unsafe { std::mem::transmute(real_malloc_addr) };
unsafe {
if !RETURN_IMMEDIATELY {
// let's do logging and other stuff that potentially
// needs malloc() itself
// This Variable prevent infinite loops because 'std::io::stdout().write_all'
// also uses malloc itself
// TODO: Do proper synchronisazion
// (lock whole method? thread_local variable?)
RETURN_IMMEDIATELY = true;
match std::io::stdout().write_all(MSG.as_bytes()) {
_ => ()
};
RETURN_IMMEDIATELY = false
}
}
(real_malloc)(bytes)
}
PS:感谢https://stackoverflow.com/a/46134764/2891595(在我搜索了很多之后,我发现了transmute的窍门!)