gpt4 book ai didi

rust - 包装 C lib 初始化/销毁例程的推荐方法

转载 作者:行者123 更新时间:2023-11-29 07:48:44 25 4
gpt4 key购买 nike

我正在为 C 库编写包装器/FFI,它需要在主线程中进行全局初始化调用以及销毁调用。

这是我目前的处理方式:

struct App;

impl App {
fn init() -> Self {
unsafe { ffi::InitializeMyCLib(); }
App
}
}

impl Drop for App {
fn drop(&mut self) {
unsafe { ffi::DestroyMyCLib(); }
}
}

可以这样使用:

fn main() {
let _init_ = App::init();
// ...
}

这工作正常,但感觉像是一个 hack,将这些调用绑定(bind)到一个不必要的结构的生命周期。将析构函数放在 finally (Java) 或 at_exit (Ruby) block 中在理论上似乎更合适。

在 Rust 中是否有更优雅的方式来做到这一点?

编辑

像这样使用这个设置(使用 lazy_static crate)而不是我上面的第二个 block 是否可能/安全:

lazy_static! {
static ref APP: App = App::new();
}

这个引用是否保证在任何其他代码之前被初始化并在退出时被销毁?在库中使用 lazy_static 是不好的做法吗?

这也将使通过这个结构访问 FFI 变得更容易,因为我不必费心传递对实例化结构的引用(在我的原始示例中称为 _init_ ).

这在某些方面也会使其更安全,因为我可以将 App 结构默认构造函数设为私有(private)。

最佳答案

除了措辞强硬的文档,我知道没有其他方法可以强制在主线程中调用方法。所以,忽略那个要求...... :-)

通常,我会使用 std::sync::Once ,这似乎基本上是为这种情况设计的:

A synchronization primitive which can be used to run a one-time global initialization. Useful for one-time initialization for FFI or related functionality. This type can only be constructed with the ONCE_INIT value.

请注意,没有任何清理规定;很多时候你只需要泄露库所做的一切。通常,如果一个库有一个专门的清理路径,它也被构造为将所有初始化数据存储在一个类型中,然后作为某种上下文或环境传递给后续函数。这会很好地映射到 Rust 类型。

警告

您当前的代码没有像您希望的那样具有保护性。由于您的 App 是一个空结构,因此最终用户可以构造它而无需调用您的方法:

let _init_ = App;

我们将使用零大小的参数来防止这种情况。另见 What's the Rust idiom to define a field pointing to a C opaque pointer?了解为 FFI 构造不透明类型的正确方法。

总而言之,我会使用这样的东西:

use std::sync::Once;

mod ffi {
extern "C" {
pub fn InitializeMyCLib();
pub fn CoolMethod(arg: u8);
}
}

static C_LIB_INITIALIZED: Once = Once::new();

#[derive(Copy, Clone)]
struct TheLibrary(());

impl TheLibrary {
fn new() -> Self {
C_LIB_INITIALIZED.call_once(|| unsafe {
ffi::InitializeMyCLib();
});
TheLibrary(())
}

fn cool_method(&self, arg: u8) {
unsafe { ffi::CoolMethod(arg) }
}
}

fn main() {
let lib = TheLibrary::new();
lib.cool_method(42);
}

关于rust - 包装 C lib 初始化/销毁例程的推荐方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36359332/

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