#callback #macro #methods #i32 #language #impl #struct

macro ffi

用于将C FFI回调路由到结构方法的过程宏

2个版本

0.1.1 2024年1月5日
0.1.0 2023年12月16日

#1829过程宏

Download history 207/week @ 2024-03-13 54/week @ 2024-03-20 48/week @ 2024-03-27 68/week @ 2024-04-03 110/week @ 2024-04-10 67/week @ 2024-04-17 52/week @ 2024-04-24 34/week @ 2024-05-01 72/week @ 2024-05-08 118/week @ 2024-05-15 164/week @ 2024-05-22 141/week @ 2024-05-29 149/week @ 2024-06-05 224/week @ 2024-06-12 119/week @ 2024-06-19 59/week @ 2024-06-26

每月585次下载
用于 2 crates

Apache-2.0

35KB
603

FFI

此crate通过提供属性#[ffi]帮助通过FFI将Rust代码暴露给其他语言,特别是C语言,该属性会自动实现从C兼容函数指针到Rust impl方法的调用转发。

这在编写可能在C程序(如QEMU)中通过dlopen调用的Rust共享库时尤其有用。

示例

在这个例子中,假设run_callback在一个你不拥有的C库中。然而,你希望使用回调注册函数的通用userdata参数来调用你的结构实例。 ffi允许你将你的impl的方法作为C FFI兼容函数导出,这样你就可以轻松地在两种语言之间进行回调。

ffi对C代码调用你的Rust代码时预期的回调类型参数顺序没有假设,因此它使得根据你的需要自定义生成变得很容易。它还提供了用于自动推导从原始指针(如From<*mut T> for &mut Foo)转换的实用工具。

use ffi::ffi;

extern "C" fn run_callback(
    callback: extern "C" fn(*mut std::ffi::c_void, i32, i32, i32) -> i32,
    data: *mut std::ffi::c_void,
) -> i32 {
    callback(data, 1, 2, 3)
}

extern "C" fn run_callback_reverse(
    callback: extern "C" fn(i32, i32, i32, *mut std::ffi::c_void) -> i32,
    data: *mut std::ffi::c_void,
) -> i32 {
    callback(1, 2, 3, data)
}


#[derive(Debug, Clone, PartialEq, Eq)]
struct Vec3 {
    x: i32,
    y: i32,
    z: i32,
}

#[ffi(from_ptr, self_ty = "*mut std::ffi::c_void")]
impl Vec3 {
    #[ffi(arg(self), arg(rest))]
    fn add(&mut self, x: i32, y: i32, z: i32) -> i32 {
        self.x += x;
        self.y += y;
        self.z += z;
        self.x + self.y + self.z
    }

    #[ffi(arg(rest), arg(self))]
    fn add_reverse_args(&mut self, x: i32, y: i32, z: i32) -> i32 {
        self.add(x, y, z)
    }
}

fn main() {
    let mut v = Vec3 { x: 1, y: 2, z: 3 };

    run_callback(vec3::add, &mut v as *mut Vec3 as *mut _);

    assert_eq!(v, Vec3 { x: 2, y: 4, z: 6 })

    run_callback_reverse(vec3::add_reverse_args, &mut v as *mut Vec3 as *mut _);

    assert_eq!(v, Vec3 { x: 3, y: 6, z: 9});
}

依赖项

~0.8–1.3MB
~28K SLoC