rust::Box公共 API:
cpp
// rust/cxx.h
template <typename T>
class Box final {
public:
using element_type = T;
using const_pointer =
typename std::add_pointer<typename std::add_const<T>::type>::type;
using pointer = typename std::add_pointer<T>::type;
Box(Box &&) noexcept;
~Box() noexcept;
explicit Box(const T &);
explicit Box(T &&);
Box &operator=(Box &&) & noexcept;
const T *operator->() const noexcept;
const T &operator*() const noexcept;
T *operator->() noexcept;
T &operator*() noexcept;
template <typename... Fields>
static Box in_place(Fields &&...);
void swap(Box &) noexcept;
// 重要:要求 `raw` 必须来自 `into_raw` 调用。不要
// 传递来自 `new` 或其他来源的指针。
static Box from_raw(T *) noexcept;
T *into_raw() noexcept;
};
限制:
Box 不支持 T 为不透明的 C++ 类型。对于在语言边界传递不透明 C++ 类型的所有权,应使用 UniquePtr 或 SharedPtr。
如果 T 是不透明的 Rust 类型,则要求该 Rust 类型为 Sized,即在编译时已知大小。未来可能会引入对动态大小的不透明 Rust 类型的支持。
示例:
以下程序使用 Box 将某些不透明的 Rust 状态的所有权传递给 C++,然后再传递回 Rust 回调函数。这是实现 FFI 异步函数的有用模式。
rust
// src/main.rs
use std::io::Write;
#[cxx::bridge]
mod ffi {
extern "Rust" {
type File;
}
unsafe extern "C++" {
include!("example/include/example.h");
fn f(
callback: fn(Box<File>, fst: &str, snd: &str),
out: Box<File>,
);
}
}
pub struct File(std::fs::File);
fn main() {
let out = std::fs::File::create("example.log").unwrap();
ffi::f(
|mut out, fst, snd| { let _ = write!(out.0, "{}{}\n", fst, snd); },
Box::new(File(out)),
);
}
cpp
// include/example.h
#pragma once
#include "example/src/main.rs.h"
#include "rust/cxx.h"
void f(rust::Fn<void(rust::Box<File>, rust::Str, rust::Str)> callback,
rust::Box<File> out);
// include/example.cc
#include "example/include/example.h"
void f(rust::Fn<void(rust::Box<File>, rust::Str, rust::Str)> callback,
rust::Box<File> out) {
callback(std::move(out), "fearless", "concurrency");
}