分配内存并调用C ++回调的Rust函数崩溃

时间:2018-05-05 11:04:14

标签: c++ rust ffi

Rust代码:

#[repr(C)]
pub struct Tmp {
    pub callback: extern "C" fn(i: i32),
}

#[no_mangle]
pub extern "C" fn set_callback(callback: extern "C" fn(i: i32)) -> *mut Tmp {
    let mut tmp = Box::new(Tmp { callback });
    println!("tmp as ptr: {:p}", tmp); // >> here <<
    &mut *tmp
}

#[no_mangle]
pub extern "C" fn use_callback(tmp_ptr: *mut Tmp) {
    unsafe {
        ((*tmp_ptr).callback)(1);
        ((*tmp_ptr).callback)(3);
    }
}

C ++代码:

struct Tmp {
    void (*callback)(int32_t);
};

typedef Tmp*(__stdcall* set_callback_t)(void(*callback_t)(int32_t));
typedef void(__stdcall* use_callback_t)(Tmp*);

void callback(int32_t i) {
    printf("%d\n", i * 2);
}

int main() {
    // ... loading rust part as .dll
    // ... checking if loaded correctly
    Tmp* tmp_ptr = set_callback(callback);
    printf("tmp_ptr %p\n", tmp_ptr);
    use_callback(tmp_ptr);
    // ... freeing the .dll
}

当我编译这个程序时,它按预期工作。 Rust和C ++中指向Tmp结构的指针的打印值匹配。当我在Rust中注释掉println时,C ++程序崩溃了,这意味着这个(可能是Rust部分)代码有问题。

我使用Rust代码作为.dll。我想将一个指向C ++函数的指针传递给set_callback函数,然后当我在C ++代码中调用use_callback时,我想在use_callback函数中使用该指针。 / p>

根据我的理解,最后我将不得不调用Rust函数来删除Tmp结构,但我把它留了出来。

1 个答案:

答案 0 :(得分:5)

Rust中的

Box与C ++中的std::unique_ptr类似。构造tmp的方式,指向的数据将在函数末尾释放。

为了将指针“泄漏”到C ++世界,你应该使用Box::into_raw

请注意,由于无法保证Rust和C ++以相同的方式分配内存;你必须将指针传递回Rust并使用Box::from_raw来解除分配。