我正在使用libjit庫來 jit 編譯函式。將函式編譯為閉包后,它回傳一個 *mut ::std::os::raw::c_void. 這個 void 指標實際上是一個我可以這樣呼叫的函式:
例如
let void_ptr = jit_function_to_closure(self.function);
let func_ptr: fn(i32, i32,i32) -> i32 = std::mem::transmute(void_ptr);
func_ptr(1,2,3);
這很好用,但需要我知道要編譯的每個函式的簽名。
我想將此片段包裝在一個接受函式指標型別的函式中,例如。fn(i32, i32,i32) -> i32作為通用引數,因此我可以回傳呼叫者指定的任何型別的函式指標。
就像是:
// My library
pub fn to_closure<T>(&self) -> T {
unsafe {
let void_ptr = jit_function_to_closure(self.function);
std::mem::transmute(void_ptr)
}
}
// Caller
let func = ....
let callable = fn(f64, f64) -> i32 = func.to_closure();
這不編譯
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> src/function.rs:57:13
|
57 | std::mem::transmute(void_ptr)
| ^^^^^^^^^^^^^^^^^^^
|
= note: source type: `*mut c_void` (64 bits)
= note: target type: `T` (this type does not have a fixed size)
這可能嗎?任意簽名的函式指標是否有通用界限?
uj5u.com熱心網友回復:
不,沒有那樣的特質。你有兩個選擇:
- 保持原樣,但由于
transmute()不能用于未知大小的型別,請使用通常的解決方法 -transmute_copy():unsafe { std::mem::transmute_copy(&void_ptr) }。 - 這就是我更喜歡的:創建一個 trait 來封裝“作為函式指標”的概念。由于 Rust 沒有可變引數,因此您必須使用宏,它不會涵蓋所有功能,但它應該涵蓋所有可用的情況。在這里,我展示了一個只為呼叫約定生成 impls 的宏
extern "C",但將其調整為使用其他呼叫約定應該不難:
trait FnPtr {
unsafe fn from_void_ptr(ptr: *mut c_void) -> Self;
}
macro_rules! impl_fnptr {
// Recursion exit condition
() => {};
($first:ident $($rest:ident)*) => {
impl<$first, $($rest,)* Ret> FnPtr for extern "C" fn($first, $($rest,)*) -> Ret {
unsafe fn from_void_ptr(ptr: *mut c_void) -> Self {
std::mem::transmute::<*mut c_void, Self>(ptr)
}
}
// With variadic args
impl<$first, $($rest,)* Ret> FnPtr for extern "C" fn($first, $($rest,)* ...) -> Ret {
unsafe fn from_void_ptr(ptr: *mut c_void) -> Self {
std::mem::transmute::<*mut c_void, Self>(ptr)
}
}
// Recurse
impl_fnptr!($($rest)*);
};
}
impl<Ret> FnPtr for extern "C" fn() -> Ret {
unsafe fn from_void_ptr(ptr: *mut c_void) -> Self {
std::mem::transmute::<*mut c_void, Self>(ptr)
}
}
// Impl up to 15 parameters.
impl_fnptr!(A B C D E F G H I J K L M N O);
但是請注意,該to_closure()功能需要標記unsafe為健全,因為您可能使用錯誤的簽名等。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/490432.html
上一篇:使用指標將值插入二維陣列
下一篇:空指標不計算為假
