在Rust中使用异物指向指针的正确方法是什么?

时间:2019-10-23 19:54:18

标签: rust ffi

我有一个DLL,可导出一堆我想在Rust中使用的C函数。我具有以下导出的函数,分别用于创建句柄和删除它的DLL API:

__declspec(dllexport) int create_handle(handle** ptr);
__declspec(dllexport) int close_handle(handle* h);

我尝试以几种不同的方式实现它,例如:

extern crate libc;

use libc::{c_int, c_float, c_void};

#[link(name = "my_dll")]
extern {
   fn create_handle(handle: *mut c_int) -> i32;
   fn close_handle(handle: i32) -> i32;
}

fn main() {
    unsafe {
        let mut ptr = 0 as i32;
        let ret = create_handle(&mut ptr);
        if ret != 0 {
            panic!("return code fail: {0}", ret);
        }

        let ret = close_handle(ptr);
        if ret != 0 {
            panic!("return code fail: {0}", ret);
        }
    }
}

尽管ptr被分配了一个值,但这不是预期的值。 close_handle本机函数检查传递的指针是否与创建的指针匹配。在此代码中,到达第二个panic!

我对Rust还是很陌生,因此目前我对指针的互操作性还不太清楚。本机函数将进行正确的类型转换,因此我应该使用c_void类型吗?还是具有指针值的i32就足够了?

1 个答案:

答案 0 :(得分:0)

这是可行的解决方案:

extern crate libc;

#[link(name = "my_dll")]
extern {
   fn create_handle(handle_ptr: *mut *mut i32) -> i32;
   fn close_handle(handle: *mut i32) -> i32;
}

fn main() {
    unsafe {
        let mut handle: *mut i32 = std::ptr::null_mut();
        let handle_ptr: *mut *mut i32 = &mut handle;

        let ret = create_handle(handle_ptr);
        if ret != 0 {
            panic!("return code fail: {0}", ret);
        }

        let ret = close_handle(handle);
        if ret != 0 {
           panic!("return code fail: {0}", ret);
        }
    }
}

解决方案是在How do I make the equivalent of a C double pointer in Rust?上找到*mut *mut符号来引用std::ptr::null_mut()