我正在尝试在Rust中实现一个基本库,它创建一个对象并将其指针返回给C.我得到的指针看起来不像它在堆上 - 当我打印它时我得到{{1} }:
0x1
C调用代码也很简单:
use std::fmt;
pub struct SndbDB {}
impl SndbDB {
fn new() -> SndbDB {
SndbDB {}
}
}
impl fmt::Display for SndbDB {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "(sndb_db)")
}
}
// Implement a destructor just so we can see when the object is destroyed.
impl Drop for SndbDB {
fn drop(&mut self) {
println!("[rust] dropping {}", self);
}
}
#[no_mangle]
pub extern "C" fn sndb_db_create() -> *mut SndbDB {
let _db = Box::into_raw(Box::new(SndbDB::new()));
println!("[rust] creating DB {:?}", _db);
_db
}
#[no_mangle]
pub unsafe extern "C" fn sndb_db_destroy(ptr: *mut SndbDB) {
println!("[rust] destroying DB {:?}", ptr);
Box::from_raw(ptr); // Rust drops this for us.
}
除了指针位置之外的所有输出都是我期望的:
typedef struct sndb_db sndb_db;
sndb_db * sndb_db_create(void);
void sndb_db_destroy(sndb_db* db);
void test_baseapi__create_and_destroy_db(void)
{
sndb_db * db = sndb_db_create();
printf("[C] Got db=%p\n",db);
sndb_db_destroy(db);
printf("[C] db should be dead by now...\n");
}
我知道在Rust中分配的内存需要被Rust解除分配 - 但是我仍然感到惊讶它使用了[rust] creating DB 0x1
[C] Got db=0x1
[rust] destroying DB 0x1
[rust] dropping (sndb_db)
[C] db should be dead by now...
的位置 - 我做错了什么,是不是很奇怪,或者这都是OK?
答案 0 :(得分:6)
看起来这是Rust的优化,因为SndbDB
结构没有状态。
向它添加一个i: u32
字段并将其传递给构造函数和C代码然后得到:
[rust] creating DB 0x7fff2fe00000
[C] Got db=0x7fff2fe00000
[rust] destroying DB 0x7fff2fe00000
[rust] dropping (sndb_db i=123)
[C] db should be dead by now...
然而,我仍然希望找到一个支持这种猜测的官方消息来源。