如何获得指向u32
值的指针?
我有一个函数指向函数:
fn getter_of_functions<T>(pointer: T) {
// ...
/*
This code don't compile ...
let fun_ptr: u32 = unsafe {
mem::transmute::<T, u32>(callback)
};
*/
}
fn function() {
println!("hello ...");
}
getter_of_functions(function);
如何获得它(我必须有一个通用的功能)?我经常犯的错误是:
cannot transmute to or from a type that contains unsubstituted type parameters
答案 0 :(得分:6)
你不能。
T
可以是任何东西;它可以是一个函数指针,u32
,i32
,f64
,String
,Box<[Arc<Mutex<Vec<&[Box<Goombah>]>>>]>
,甚至()
:什么都没有。编译器无法知道转换是否是远程可能,更不用说正确。
这是因为你没有有一个函数采用“指向函数的指针”。你有一个“绝对任何东西”的功能。如果您正在处理像C ++ / D模板这样的Rust泛型,那么您需要了解它们的工作方式不同。 Rust根据您所说的关于所涉及类型的内容,在定义时检查其模板。例如,你可以用完全通用的T
做的唯一事就是移动它。你已经实例化了泛型函数,使得T
是一个函数类型是无关紧要的:到那时,Rust已经决定了通用代码是否有效。
使用不同的类比:Rust泛型是C ++模板,C ++输入是Python输入的类型:静态和提前完成而不是ad-hoc和按需完成。
那么,你如何指定你想要某种指向函数的指针?你不能。
无法指定任何类型的函数指针。 Rust没有可变参数泛型,因此您无法表达参数列表所需的可变数量类型的想法。
有Fn*
特征,但使用这些特征只会使情况变得更糟。既然你没有解释为什么你正试图这样做,那么很难知道你应该做什么。
所能做的是询问函数指针的特定形状。
fn getter_0_args<R>(f: fn() -> R) { ... }
fn getter_2_args<A0, A1, R>(f: fn(A0, A1) -> R) { ... }
或者您可以在调用代码中执行强制转换:
getter_1_arg(f as fn(_) -> _ as usize)
(我在这里使用_
让推理填充参数并为我返回类型。)
这让我想到了我的最后一点:当as
正常工作时,使用transmute 完全 。另外,使用u32
错误:您应该使用usize
或isize
来处理指针和长度的内容。
答案 1 :(得分:0)
您可能希望将函数指针强制转换为usize
而不是u32
。
fn foo(ptr: fn()) {
let n = ptr as usize;
println!("{}", n);
}
fn a() {}
fn b() {}
fn main() {
foo(a);
foo(b);
}
答案 2 :(得分:0)
fn
- 指针似乎没有实现任何你可以依赖的有用的共同特征作为约束。如果他们至少实现Into<usize>
或Into<*mut T>
会很好,但由于他们不这样做,诀窍是创建自己的特征并使用一些宏魔法为所有{{1}实现它-pointers到某个arity。这就是我为minhook-rs做的。
这是一个简化的实现:
fn
如前所述,您应使用use std::mem;
pub trait Function: Sized {
unsafe fn from_usize(value: usize) -> Self;
fn to_usize(&self) -> usize;
}
macro_rules! impl_function {
(recurse: () ($($ty:ident),*)) => {
impl_function!(impl_cc: ($($ty),*));
};
(recurse: ($hd:ident $(, $tl:ident)*) ($($ty:ident),*)) => {
impl_function!(impl_cc: ($($ty),*));
impl_function!(recurse: ($($tl),*) ($($ty,)* $hd));
};
(impl_cc: ($($ty:ident),*)) => {
impl_function!(impl_fun: ($($ty),*) ( fn($($ty),*) -> Ret));
// impl_function!(impl_fun: ($($ty),*) (extern "cdecl" fn($($ty),*) -> Ret));
// impl_function!(impl_fun: ($($ty),*) (extern "stdcall" fn($($ty),*) -> Ret));
// impl_function!(impl_fun: ($($ty),*) (extern "fastcall" fn($($ty),*) -> Ret));
// impl_function!(impl_fun: ($($ty),*) (extern "win64" fn($($ty),*) -> Ret));
// impl_function!(impl_fun: ($($ty),*) (extern "C" fn($($ty),*) -> Ret));
// impl_function!(impl_fun: ($($ty),*) (extern "system" fn($($ty),*) -> Ret));
// Uncomment/add more if needed
};
(impl_fun: ($($ty:ident),*) ($fn_type:ty)) => {
impl<Ret, $($ty),*> Function for $fn_type {
unsafe fn from_usize(value: usize) -> Self {
mem::transmute(value)
}
fn to_usize(&self) -> usize {
*self as usize
}
}
};
($($ty:ident),*) => {
impl_function!(recurse: ($($ty),*) ());
};
}
// Implement Function for up to 12 arguments
impl_function!(A, B, C, D, E, F, G, H, I, J, K, L);
fn getter_of_functions<F: Function>(function: F) {
let fun_ptr = function.to_usize();
println!("{:x}", fun_ptr);
}
fn function() {
println!("hello ...");
}
fn main() {
getter_of_functions(function as fn());
}
而不是usize
。