Function 如何获取函数作为u32的指针?

Function 如何获取函数作为u32的指针?,function,pointers,rust,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() {

如何获取指向函数的指针作为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);

您可能希望将函数指针强制转换为usize,而不是u32


您可能希望将函数指针强制转换为usize,而不是u32

你不能

它可以是任何东西;它可以是函数指针、u32、i32、f64、字符串、框,甚至:什么都没有。编译器无法知道转换是否有可能,更不用说正确了

这是因为您没有一个函数使用指向函数的指针。你有一个函数,绝对可以接受任何东西。如果您像对待C++/D模板一样对待Rust泛型,那么您需要了解它们的工作方式不同。Rust在定义时根据您告诉它的相关类型检查其模板。例如,使用完全通用的T可以做的唯一一件事就是移动它。你已经实例化了泛型函数,使得T是一个函数类型,这是不相关的:到那时,Rust已经决定了泛型代码是否有效

使用不同的类比:Ru锈类泛型是C++模板,C++类型是Python打字:静态的,提前完成,而不是临时的,按需完成。 那么,如何指定需要某种指向函数的指针呢?你不能

无法指定任意类型的函数指针。Rust没有可变的泛型,因此您无法表达变数类型的概念,这是参数列表所需要的

有Fn*的特点,但使用这些只会让情况变得更糟。因为你还没有解释你为什么要这么做,所以很难知道你应该做什么

您可以要求函数指针的特定形状

fn getter_0_args<R>(f: fn() -> R) { ... }
fn getter_2_args<A0, A1, R>(f: fn(A0, A1) -> R) { ... }
我在这里使用u,让推理为我填充参数和返回类型

这就引出了我的最后一点:在as工作正常的情况下,使用transmute进行转换是完全没有必要的。此外,使用u32进行此操作是错误的:您应该使用usize或isize进行指针大小和长度大小的操作。

您不能这样做

它可以是任何东西;它可以是函数指针、u32、i32、f64、字符串、框,甚至:什么都没有。编译器无法知道转换是否有可能,更不用说正确了

这是因为您没有一个函数使用指向函数的指针。你有一个函数,绝对可以接受任何东西。如果您像对待C++/D模板一样对待Rust泛型,那么您需要了解它们的工作方式不同。Rust在定义时根据您告诉它的相关类型检查其模板。例如,使用完全通用的T可以做的唯一一件事就是移动它。你已经实例化了泛型函数,使得T是一个函数类型,这是不相关的:到那时,Rust已经决定了泛型代码是否有效

使用不同的类比:Ru锈类泛型是C++模板,C++类型是Python打字:静态的,提前完成,而不是临时的,按需完成。 那么,如何指定需要某种指向函数的指针呢?你不能

无法指定任意类型的函数指针。Rust没有可变的泛型,因此您无法表达变数类型的概念,这是参数列表所需要的

有Fn*的特点,但使用这些只会让情况变得更糟。因为你还没有解释你为什么要这么做,所以很难知道你应该做什么

您可以要求函数指针的特定形状

fn getter_0_args<R>(f: fn() -> R) { ... }
fn getter_2_args<A0, A1, R>(f: fn(A0, A1) -> R) { ... }
我在这里使用u,让推理为我填充参数和返回类型

这就引出了我的最后一点:在as工作正常的情况下,使用transmute进行转换是完全没有必要的。此外,使用u32是错误的:对于指针大小和长度大小的东西,应该使用usize或isize。

fn指针似乎没有实现任何有用的通用特性,您可以依赖这些特性作为边界。如果它们至少实现到或实现到中,那就好了,但既然它们没有实现,关键是创建您自己的trait,并使用一些宏魔法来实现所有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而不是u32。

fn指针似乎没有实现任何可用的通用特性,您可以依赖它作为边界。如果它们至少实现到或实现到中,那就好了,但既然它们没有实现,关键是创建您自己的trait,并使用一些宏魔法来实现所有fn指针,直到达到某个算术数。我就是这样做的

下面是一个简化的实现 n:


如前所述,您应该使用usize而不是u32。

是的,这段代码可以工作,但我是如何说我想要一个泛型函数的。我不知道怎么做。是的,这段代码很有效,但我说我想要一个泛型函数。我不知道怎么做。
getter_1_arg(f as fn(_) -> _ as usize)
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());
}