导出一个类:
首先用c写一个c的结构,模拟类的操作,也就是c函数的第一个指针是结构体指针,模拟类的this指针。
然后再把c的函数导出到rust
以DB为例:
- 在librocksdb_sys/crocksdb/c.cc中导出c的函数
struct crocksdb_t {
DB* rep;
};
crocksdb_t* crocksdb_open(const crocksdb_options_t* options, const char* name,
char** errptr) {
DB* db;
if (SaveError(errptr, DB::Open(options->rep, std::string(name), &db))) {
return nullptr;
}
crocksdb_t* result = new crocksdb_t;
result->rep = db;
return result;
}
- librocksdb_sys/crocksdb/crocksdb/c.h中定义。
extern C_ROCKSDB_LIBRARY_API crocksdb_t* crocksdb_open(
const crocksdb_options_t* options, const char* name, char** errptr);
- 用 ./scripts/generate-bindings.sh 重新生成绑定,即生成到了 x86_64-unknown-linux-gnu-bindings.rs中
- 复制 x86_64-unknown-linux-gnu-bindings.rs 中的函数定义到 librocksdb_sys/src/lib.rs 中,定一个空指针,例如 DBInstance
#[repr(C)]
pub struct DBInstance(c_void);
pub fn crocksdb_open(
options: *mut Options,
path: *const c_char,
err: *mut *mut c_char,
) -> *mut DBInstance;
- 在src/rocksdb.rs中定义类名
pub DB{
inner: *mut DBInstance,
}
impl{
pub fn open_cf_with_ttl<'a, T>(
...
) -> Result<DB, String>{
unsafe{
DB{inner:crocksdb_ffi::crocksdb_open(...)}
}
}
主要是这样的一个流程。先导出成C的函数,然后导出成rust的。其中第4步的函数就是第2步的函数。