Rust如何从现有函数推断类型,将FARPROC转换为对应可调用函数类型
问题根因
你当前实现出错的核心原因有两个:
- Rust中函数项类型(直接使用函数名得到的独有零大小类型)和函数指针类型是完全不同的类型,你原实现的泛型
F被推导为传入样本函数的独有函数项类型,而非你需要的对应签名的函数指针类型,导致类型转换结果完全不符合预期。 transmute_copy的用法有误:FARPROC本身就是函数指针类型,不需要对它取地址再转换,直接转换FARPROC自身的值即可。
可行实现
可以通过泛型约束,让Rust自动从样本函数推导目标函数指针的类型,实现你要的DRY效果:
use std::mem::transmute; use std::os::raw::{c_void, c_char}; // 定义FARPROC类型,和Win32定义对齐 pub type FARPROC = unsafe extern "system" fn() -> isize; /// 转换FARPROC为和样本函数签名一致的函数指针类型 /// # Safety /// 必须保证传入的FARPROC对应的实际函数签名、ABI和样本函数完全一致 pub unsafe fn cast_to_function<F>(addr: FARPROC, _sample: F) -> F where F: Copy, // 所有函数指针都满足Copy约束 { transmute(addr) }
使用示例
// 样本函数:ABI必须用extern "system"和Win32函数对齐,仅用作签名模板,不会被实际调用 pub extern "system" fn foo(_arg1: i32, _arg2: c_void, _arg3: *const c_char) { // 实现可以留空 } // 假设你已经获取到FARPROC let address: FARPROC = unsafe { GetProcAddress(module, proc_name).unwrap() }; // 自动推导目标类型,as _ 强制把函数项转换为函数指针类型 let function = unsafe { cast_to_function(address, foo as _) }; // 正常调用即可 unsafe { function(1, std::ptr::null_mut() as _, c"test".as_ptr()) };
如果不想每次调用都写as _,可以调整辅助函数的参数为引用,触发自动类型转换:
pub unsafe fn cast_to_function<F>(addr: FARPROC, _sample: &F) -> F where F: Copy, { transmute(addr) } // 调用时直接传引用即可 let function = unsafe { cast_to_function(address, &foo) };
注意事项
- 样本函数的ABI必须声明为
extern "system",和Win32 API的调用约定对齐,否则会触发未定义行为。 - 整个转换过程是unsafe的,Rust无法校验你传入的
FARPROC对应的实际函数签名是否和样本函数匹配,需要你自行保证正确性。
内容的提问来源于stack exchange,提问作者arslancharyev31
相关产品推荐
相关产品推荐

