Rust 中的 XPCOM 组件¶
XPCOM 组件可以用 Rust 编写。
一个简单的例子¶
以下示例展示了一个实现 nsIObserver
的新类型。
首先,创建一个新的空 crate(例如,使用 cargo init --lib
),并在其 Cargo.toml
文件中添加以下依赖项。
[dependencies]
libc = "0.2"
nserror = { path = "../../../xpcom/rust/nserror" }
nsstring = { path = "../../../xpcom/rust/nsstring" }
xpcom = { path = "../../../xpcom/rust/xpcom" }
(../
出现的次数取决于 crate 在文件层次结构中的深度。)
接下来,根据 构建文档将其挂接到构建系统中。
Rust 代码需要导入一些基本类型。 xpcom::interfaces
包含所有常用的 nsI
接口。
use libc::c_char;
use nserror::nsresult;
use std::sync::atomic::{AtomicBool, Ordering};
use xpcom::{interfaces::nsISupports, RefPtr};
下一部分声明了实现。
#[xpcom(implement(nsIObserver), atomic)]
struct MyObserver {
ran: AtomicBool,
}
这定义了实现类型,该类型将以指定的方式进行引用计数并实现列出的 xpidl 接口。它还将声明第二个初始化器结构体 InitMyObserver
,该结构体可用于使用 MyObserver::allocate
方法分配新的 MyObserver
。
接下来,所有接口方法都在 impl
块中声明为 unsafe
方法。
impl MyObserver {
#[allow(non_snake_case)]
unsafe fn Observe(
&self,
_subject: *const nsISupports,
_topic: *const c_char,
_data: *const u16,
) -> nsresult {
self.ran.store(true, Ordering::SeqCst);
nserror::NS_OK
}
}
这些方法始终采用 &self
,而不是 &mut self
,因此我们需要使用内部可变性:AtomicBool
、RefCell
、Cell
等。这是因为所有 XPCOM 对象都是引用计数的(如 Arc<T>
),因此无法提供独占访问。
XPCOM 方法默认情况下是不安全的,但可以使用 xpcom_method! 宏来清理它。它还负责空值检查和隐藏引用后面的指针,允许您返回 Result
而不是 nsresult,
等等。
要在 Rust 代码中使用此类型,请执行以下操作。
let observer = MyObserver::allocate(InitMyObserver {
ran: AtomicBool::new(false),
});
let rv = unsafe {
observer.Observe(x.coerce(),
cstr!("some-topic").as_ptr(),
ptr::null())
};
assert!(rv.succeeded());
该实现具有一个(自动生成的)allocate
方法,该方法接收初始化结构体并返回对实例的 RefPtr
。
coerce
将任何 XPCOM 对象转换为其基接口之一;在本例中,基接口为 nsISupports
。在 C++ 中,这将通过继承自动处理,但 Rust 没有继承,因此转换必须是显式的。
更复杂的例子¶
以下 XPCOM 组件是用 Rust 编写的。
kvstore,它通过 Rkv 库 公开了 LMDB 键值存储。API 是异步的,使用
moz_task
在后台线程上调度所有 I/O,并支持获取、设置和迭代键。cert_storage,它存储 已吊销的中间证书 列表。
bookmark_sync,它 合并 来自 Firefox Sync 的书签与 Places 数据库中的书签。 还有一些关于 Rust 如何与 Sync 交互的文档
webext_storage_bridge,它为 WebExtension storage.sync API 提供支持。它是一个独立的示例,从应用程序服务中提取了一个 crate 来进行繁重的工作,将其包装在一个 Rust XPCOM 组件中,然后将组件包装在一个 JS 接口中。那里还有一些关于添加
components.conf
文件和声明组件构造函数的虚拟 C++ 头文件的样板文件。 它有一些关于其如何组合在一起的深入文档。