如何获得一个指向u32功能的指针?

时间:2016-03-30 21:58:22

标签: function pointers rust

如何获得指向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

3 个答案:

答案 0 :(得分:6)

你不能。

T可以是任何东西;它可以是一个函数指针,u32i32f64StringBox<[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 错误:您应该使用usizeisize来处理指针和长度的内容。

答案 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