You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 18:54:01