gpt4 book ai didi

c - 为外部 C 库分配不透明缓冲区的正确 Rust 方法是什么?

转载 作者:太空宇宙 更新时间:2023-11-04 02:20:59 25 4
gpt4 key购买 nike

我有一个外部库(例如 libcisland.so),其界面如下:

size_t lib_handle_size();
typedef void* handle;
int lib_init(handle h);
int lib_store(handle h, int value);
int lib_restore(handle h, int *pvalue);

此库的用户应执行以下操作:

// allocate some buffer in client address space
handle h = malloc(lib_handle_size());
// pass this buffer to library for initialization
if (lib_init(h)) { /* handle errors */ }
// library initializes this handle by some opaque fashion
// then user uses it
lib_store(h,42);
int r;
lib_restore(h,&r);
// after all work is done, user frees this handle
free(h);

我不知道如何正确地将此接口(interface)包装到 Rust。这就是我的结局:

pub struct Island {
h: Handle,
v: Vec<u8>,
}

impl Island {
pub fn new() -> Island {
let len = unsafe { lib_handle_size() };
let mut v: Vec<u8> = Vec::with_capacity(len);
let h: Handle = v.as_mut_ptr();
Island { v:v, h:h, }
}

pub fn store(&mut self, v: i32) {
unsafe { lib_store(self.h, v); }
}

pub fn restore(&mut self) -> i32 {
let mut v = 0;
unsafe { lib_restore(self.h, &mut v); }
v
}
}

impl Drop for Island {
fn drop(&mut self) {
drop(&mut self.v);
}
}

/// unsafe part
use libc::size_t;
pub type Handle = *mut u8;
#[link(name="cisland")]
extern {
pub fn lib_handle_size() -> size_t;
pub fn lib_init(h: Handle) -> i32;
pub fn lib_store(h: Handle, value: i32) -> i32;
pub fn lib_restore(h: Handle, pvalue: &mut i32) -> i32;
}

为此目的使用 Vec(u8) 可以吗?此 Drop 特性是否正确实现?

最佳答案

Is it Ok to use Vec(u8) for this purpose?

我认为Vec<u8>没关系,但你应该初始化它而不是使用零长度 vector ,指向未初始化的内存。使用 Box<[u8]> 也会更稳健因为这将强制它不能被意外重新分配。

Is this Drop trait implemented properly?

应该没有必要实现Drop根本。 Island的领域无论如何,每个都会正确掉落。

我不是存储句柄,而是每次使用方法获取它。那么你的结构就简单多了。

use libc::c_void;

pub struct Island {
buf: Box<[u8]>,
}

impl Island {
pub fn new() -> Island {
let len = unsafe { lib_handle_size() };
let v: Vec<u8> = vec![0; len];
Island { buf: v.into_boxed_slice() }
}

pub fn store(&mut self, v: i32) {
unsafe { lib_store(self.handle_mut(), v); }
}

pub fn restore(&mut self) -> i32 {
let mut v = 0;
unsafe { lib_restore(self.handle_mut(), &mut v); }
v
}

fn handle_mut(&mut self) -> *mut c_void {
self.buf.as_mut_ptr() as *mut c_void
}
}

你不需要 Drop实现因为 Box当它超出范围时会自动丢弃(就像 Vec 一样)。

关于c - 为外部 C 库分配不透明缓冲区的正确 Rust 方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58231215/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com