Предоставить аргумент `char **` для функции C из Rust? - PullRequest
0 голосов
/ 20 мая 2018

У меня есть функция C, которая (упрощенно) выглядит так:

static char buffer[13];

void get_string(const char **s) {
    sprintf(buffer, "Hello World!");
    *s = buffer;
}

Я объявил ее в Rust:

extern pub fn get_string(s: *mut *const c_char);

Но я не могу понятьиз требуемого заклинания вызвать его и преобразовать результат в строку Rust.Все, что я пробовал, либо не компилируется, либо вызывает SEGV.

Есть указатели?

Ответы [ 2 ]

0 голосов
/ 21 мая 2018

Объединение Передача переменной Rust в функцию C, которая ожидает ее изменения

unsafe { 
    let mut c_buf = std::ptr::null();
    get_string(&mut c_buf);
}

С Как преобразовать строку C в строку Rustи обратно через FFI? :

extern crate libc;

use libc::c_char;
use std::ffi::CStr;
use std::str;

extern "C" {
    fn get_string(s: *mut *const c_char);
}

fn main() {
    unsafe {
        let mut c_buf = std::ptr::null();
        get_string(&mut c_buf);
        let c_str = CStr::from_ptr(c_buf);
        let str_slice: &str = c_str.to_str().unwrap();
        let str_buf: String = str_slice.to_owned(); // if necessary
    };
}
0 голосов
/ 21 мая 2018

Прежде всего, char в Rust равно , а не эквивалентно char в C :

Тип char представляет один символ.Более конкретно, поскольку «символ» не является четко определенным понятием в Юникоде, char является « скалярным значением Юникода », которое аналогично, но не совпадает с «* 1016».* Кодовая точка Unicode '.

В Rust вы можете использовать u8 или i8 в зависимости от операционной системы.Вы можете использовать std::os::raw::c_char для этого:

Эквивалент типа C char.

C char type isполностью отличается от Rust's char type ;в то время как тип Rust представляет скалярное значение в юникоде, тип C char представляет собой обычное целое число.Этот тип всегда будет i8 или u8, так как тип определяется как длина одного байта.

Символы C чаще всего используются для создания строк C.В отличие от Rust, где длина строки включена вместе со строкой, строки C отмечают конец строки символом '\0'.См. CStr для получения дополнительной информации.

Сначала нам понадобится переменная, которую можно передать функции:

let mut ptr: *const c_char = std::mem::uninitialized();

Чтобы передать еекак *mut вы можете просто использовать ссылку:

get_string(&mut ptr);

Теперь используйте *const c_char для создания CStr:

let c_str = CStr::from_ptr(ptr);

Для преобразованияВы можете выбрать String:

c_str.to_string_lossy().to_string()

или

c_str().to_str().unwrap().to_string()

Однако вы не должны использовать String, если вам это не нужно.В большинстве сценариев Cow<str> удовлетворяет потребности.Его можно получить с помощью c_str.to_string_lossy():

Если содержимое CStr является действительными данными UTF-8, эта функция вернет Cow::Borrowed([&str]) с соответствующим срезом [&str].В противном случае он заменит любые недопустимые последовательности UTF-8 на U+FFFD REPLACEMENT CHARACTER и вернет Cow::[Owned](String) с результатом.

Вы можете увидеть это в действии на Playground . Эта игровая площадка показывает использование с to_string_lossy().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...