use std::{ffi::c_void, marker::PhantomData};
struct CBProxy<F, Sig>(PhantomData<(F, Sig)>);
impl<F, A1, A2, R> CBProxy<F, fn(A1, A2) -> R>
where
F: FnMut(A1, A2) -> R,
{
unsafe extern "C" fn cb(vp: *mut c_void, a1: A1, a2: A2) -> R {
let fp = vp as *mut F;
let f = &mut *fp;
f(a1, a2)
}
}
pub(crate) trait MakeCVoidCB<CF> {
fn get_c_void_cb(&mut self) -> CF;
}
impl<F, A1, A2, R> MakeCVoidCB<unsafe extern "C" fn(*mut c_void, A1, A2) -> R> for F
where
F: FnMut(A1, A2) -> R,
{
fn get_c_void_cb(&mut self) -> unsafe extern "C" fn(*mut c_void, A1, A2) -> R {
CBProxy::<F, fn(A1, A2) -> R>::cb
}
}
let mut cb = |a, b| {todo!()};
let cbmp = &mut cb;
let ccb = cbmp.get_c_void_cb();
let cbvp = cbmp as *mut _ as *mut c_void;
let ret = f(self, cbvp, ccb);另一个参考链接: https://gist.github.com/XeCycle/beeb34e9e1539cc314fbec04a3fbeaa8
use std::ffi::c_void;
struct CCb(unsafe extern "C" fn(i32, *mut c_void), *mut c_void);
impl CCb {
unsafe fn call(self, arg: i32) {
self.0(arg, self.1)
}
}
#[no_mangle]
extern "C" fn test_rs_lib(cb: unsafe extern "C" fn(i32, *mut c_void), ctx: *mut c_void) {
let ccb = CCb(cb, ctx);
unsafe {
ccb.call(42);
}
}test.c
#include <stdio.h>
void test_rs_lib(void (*cb)(int, void*), void*);
void my_cb(int a, void* ctx)
{
*((int*)ctx) = a;
}
int main()
{
int saved = 0;
test_rs_lib(&my_cb, &saved);
printf("%d\n", saved);
}