在Rust中,在外部函数中使用指向指针的指针的正确方法是什么?

在Rust中,在外部函数中使用指向指针的指针的正确方法是什么?,rust,ffi,Rust,Ffi,我有一个DLL,它导出了一堆我想在Rust中使用的C函数。我有以下导出函数,分别用于为DLL API创建句柄和删除句柄: \u declspec(dllexport)int创建句柄(句柄**ptr); __declspec(dllexport)int close_handle(handle*h); 我尝试了几种不同的方式来实现它,例如: extern crate libc; use libc::{c_int, c_float, c_void}; #[link(name = "my_dll"

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

\u declspec(dllexport)int创建句柄(句柄**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\u handle
本机函数检查传递的指针是否与创建的指针匹配。在这段代码中,第二个
panic已到达


我是个新手,所以指针的互操作性目前对我来说不是很清楚。本机函数将执行正确的类型转换,因此我应该使用
c\u void
类型吗?或者带有指针值的
i32
是否足够

以下是有效的解决方案:

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);
        }
    }
}

解决方案是使用
*mut*mut
符号来引用上的
std::ptr::null_mut()

很难回答您的问题,因为它不包含。我们无法确定代码中存在的类型(
句柄
)或函数(
创建句柄
/
关闭句柄
)是什么。您的函数声明为
(句柄**ptr)
,但与之等价的函数是
(句柄:.mut c_int)
。你为什么认为这些是等价的类型?你的问题可以用的答案来回答。如果没有,请回答您的问题以解释差异。否则,我们可以将此问题标记为已回答。@Shepmaster修复了图像导入(它是更大程序的一部分,我复制错误)。感谢您提供有关修订历史记录的信息。我不知道如何在没有DLL的情况下包含最小的可复制示例。我将检查提供的链接并进行后续操作。最小化的DLL代码可能会归结为每个函数一到两条语句,再加上
handle
的定义,总共可能有10行。这很容易包括在内,也是创建一个。