Как правильно использовать указатель на указатель во внешней функции в Rust? - PullRequest
0 голосов
/ 23 октября 2019

У меня есть DLL, которая экспортирует кучу функций C, которые я хотел бы использовать в Rust. У меня есть следующие экспортированные функции, которые используются для создания дескриптора и удаления его для 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 голосов
/ 23 октября 2019

Вот рабочее решение:

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(), найденная на Как сделать эквивалент двойного указателя C вРжавчина .

...