练习实现 cdylib,卡住了,有没有使用类似技术开源的项目可以学习一下?

2022-12-02 22:13:57 +08:00
 wsa10054

现有项目由 rust 实现,现在希望将部分功能封装为 C 动态库,给其他语言使用。C 库 API 使用流程是这样的:

// 不透明指针,需要使用方持有
#define Ctx void *;

// 第 1 步 初始化 Ctx,然后将指针传给使用方
int32_t ctx_open(Ctx *ctx);

// 第 2 步 调用相关功能接口时,需要将 ctx 传
int32_t ctx_use(Ctx ctx);

// 第 3 步 使用方用该方法来完成资源释放
int32_t ctx_close(Ctx ctx);

对 rust unsafe 部分不熟悉,在裸指针转换以及 Ctx 生命周期维护上卡住了。

我现在的代码大概是这样的

pub type Ptr = *mut ffi::c_void;

#[no_mangle]
pub extern "C" fn ctx_open(handle: *mut Ptr) -> i32 {
    let ctx: Box<Ctx> = Box::new(Ctx {  });
    let ptr = Box::<Ctx>::into_raw(ctx);
    let ptr = ptr as Ptr;
    unsafe {*handle = ptr};
    0
    // 我希望 ctx 不会因为离开作用域而自动 drop,我不确定以上代码是否正确
}

#[no_mangle]
pub extern "C" fn ctx_use(handle: Ptr) -> i32 {
    //  这应该需要将 handle 转换为 Ctx 可可变借用(如果不是借用,可能会导致 Ctx 对象在这个函数结束就释放了),不知道怎么做
}

#[no_mangle]
pub extern "C" fn ctx_close<'a>(handle: Ptr)-> i32 {
    let mut ctx = unsafe { Box::<Ctx>::from_raw(handle as *mut Ctx)};
    unsafe {drop(yy)};
    0
    // 释放掉资源,不知道是否正确
}
1784 次点击
所在节点    Rust
5 条回复
bearice
2022-12-02 23:42:08 +08:00
1) The into_raw function consumes a box and returns the raw pointer. It doesn’t destroy T or deallocate any memory.
2) let ctx : &Ctx= unsafe { &*handle.cast() };
3) 没错
sosilver
2022-12-02 23:47:28 +08:00
rust 这边没必要用 void *,写个*mut T 还清楚些;
怎么获得引用?当然是 dereferencing ;
使用指针时注意判断 null
sosilver
2022-12-03 00:22:42 +08:00
翻了下 wasmer 和 slint-ui 的 ffi ,*mut T, &mut T, Option<&mut T>, Option<Box<T>>啥都在用,也没什么检查,看来还是怎么方便怎么来🤣
wsa10054
2022-12-03 11:59:16 +08:00
@bearice
@sosilver
谢啦!
elden
2022-12-03 13:36:35 +08:00
可以试试 safer_ffi ,更容易 /安全地写 FFI 胶水代码。
cppc
2022-12-04 13:09:10 +08:00
Rust FFI Omnibus 是使用 Rust 编写代码 用到 其他语言 的示例集合.

http://llever.com/rust-ffi-omnibus/

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/899714

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX