2017-01-19 20 views
3

У меня есть функция C:Как преобразовать символ в libc :: c_char?

Node * first_element_by_path(const Node * node, const char * path, char delimiter); 

и функцию клея ржавчины:

pub fn first_element_by_path(node: *mut CNode, path: *const c_char, delimiter: c_char) -> *mut CNode; 

Он ожидает, что в c_char в качестве разделителя. Я хочу послать char, но c_char является i8, а не char. Как я могу конвертировать Rust char в i8 или c_char в этом случае?

ответ

9

Вы задаете вопрос:

Как поместиться 32-разрядное число в 8-битное значение?

Который имеет немедленный ответ: «выбросить большую часть битов»:

let c = rust_character as libc::c_char; 

Однако, это должно заставить вас остановиться и задать вопросы:

  • Перечислим остальные бит в правильной кодировке?
  • Как насчет всех этих бит, которые я выбросил?

Rust char s разрешает кодирование всех сканирующих значений Unicode. Что такое вашего желаемого поведения для этого кода:

let c = '' as libc::c_char; 

Это, вероятно, не создавать значение -87, значение не-ASCII! Или это менее глупо и, возможно, более реалистичный вариант, который -17:

let c = 'ï' as libc::c_char; 

Вы тогда должны спросить: что делает код C означает, по характеру? Какова кодировка строк кода C? Как код C обрабатывает текст без ASCII?

Самое безопасное может утверждать, что значение находится в пределах диапазона ASCII:

let c = 'ï'; 
let v = c as u32; 
assert!(v <= 127, "Invalid C character value"); 
let v = v as libc::c_char; 

Вместо того, чтобы утверждать, вы можете также вернуть Result тип, который указывает, что значение было вне диапазона.

Я должен изменить свою функцию (тот, который будет вызывать функцию клея), чтобы получить c_char вместо char?

Это зависит. Это может просто подтолкнуть проблему вверх по стеку; теперь каждый вызывающий должен решить, как создать c_char и беспокоиться о значениях между 128 и 255. Если семантика вашего кода такова, что значение должно быть символом ASCII, то кодирует это в ваших типах. В частности, вы можете использовать что-то вроде ascii crate.

В любом случае вы нажимаете на возможность отказа от чужого кода, что облегчает вашу жизнь с потенциальным расходом, чтобы сделать вызывающего абонента более расстроенным.

+0

Сделать утверждение будет правильным способом его обработки или изменить мою функцию (ту, которая вызовет функцию клея), чтобы получить 'c_char' вместо' char'? – Sassa

+2

Большое спасибо за подробный и очень проницательный ответ! – Sassa