2个稳定版本
1.1.0 | 2024年5月12日 |
---|---|
1.0.0 | 2024年2月24日 |
#93 in FFI
18KB
270 行
ffi-closure - 通过FFI发送和接收闭包
特性
- 简单的API
- 允许通过FFI边界发送Rust函数和闭包
no-std
兼容- 支持多种调用约定(默认为C调用约定)
- 简化了与FFI 闭包样 函数的交互
- 闭包可以有析构函数
- 可以指定闭包的线程安全级别(None,
Send
,Sync
或Send + Sync
)
示例
导出闭包
use ffi_closure::Closure;
use std::ffi::c_void;
# mod sys {
# use core::ffi::c_void;
# #[no_mangle]
# unsafe extern "C" fn some_lib_fn(f: unsafe extern "C" fn(i8, *mut c_void), user_data: *mut c_void) { f(-1, user_data) }
# }
extern "C" {
fn some_lib_fn(f: unsafe extern "C" fn(i8, *mut c_void), user_data: *mut c_void);
}
pub fn main() {
let weight = std::env::args().len() as i8;
let closure = Closure::<dyn FnMut(i8)>::new(move |x| println!("{}", x * weight));
let (f, user_data): (unsafe extern "C" fn(i8, *mut c_void), *mut c_void) = closure.as_extern_parts();
unsafe {
some_lib_fn(f, user_data);
}
}
具有系统调用约定的导出闭包
use ffi_closure::{Closure, cc::System};
use std::ffi::c_void;
# mod sys {
# use core::ffi::c_void;
# #[no_mangle]
# unsafe extern "C" fn some_lib_fn(f: unsafe extern "C" fn(i8, *mut c_void), user_data: *mut c_void) { f(-1, user_data) }
# }
extern "C" {
fn some_lib_fn(f: unsafe extern "system" fn(i8, *mut c_void), user_data: *mut c_void);
}
pub fn main() {
let weight = std::env::args().len() as i8;
let closure = Closure::<dyn FnMut(i8), System>::new(move |x| println!("{}", x * weight));
let (f, user_data): (unsafe extern "system" fn(i8, *mut c_void), *mut c_void) = closure.as_extern_parts();
unsafe {
some_lib_fn(f, user_data);
}
}
导入闭包
use ffi_closure::Closure;
use std::ffi::c_void;
#[no_mangle]
pub extern "C" fn some_lib_fn(
f: unsafe extern "C" fn(i8, *mut c_void),
user_data: *mut c_void,
) {
let mut f = unsafe { Closure::<dyn FnMut(i8)>::from_extern(f, user_data, None) };
for i in 0..10 {
f(i);
}
}
线程安全的导入闭包
use ffi_closure::{Closure};
use std::ffi::c_void;
#[no_mangle]
pub unsafe extern "C" fn some_lib_fn(
f: unsafe extern "C" fn(i8, *mut c_void),
user_data: *mut c_void,
) {
// SAFETY: Caller must ensure the passed function pointer and user data are thread-safe.
let mut f = unsafe { Closure::<dyn Send + FnMut(i8)>::from_extern(f, user_data, None) };
std::thread::spawn(move || {
for i in 0..10 {
f(i);
}
});
}
注意
为了使Closure
实现FnOnce
和FnMut
,必须启用'nightly'功能(因此,程序必须使用nightly Rust构建)。对于非nightly版本,请使用Closure::call
依赖关系
~1.5MB
~35K SLoC