Вы можете свободно, но небезопасно звонить из C в Rust и из Rust в C.
Из Rust в C: напишите блок extern "C"
с прототипами C функций.
От C до Rust: напишите функцию Rust с префиксом #[no_mangle] extern "C"
. Вы должны убедиться, что любое полученное или возвращаемое значение является FFI-дружественным: базовые c типы или repr(C)
типы или необработанные указатели на те и некоторые другие.
Также вам потребуются объявления, эквивалентные C объявлениям Rust. для этого вы можете использовать типы в std::os::raw
, std::ffi
и внешний ящик libc
.
В частности, ответ на ваши вопросы об указателях функций, например, в C:
typedef int (*callback)(uint8_t *data, size_t len);
переводится на Rust как:
type Callback = unsafe extern "C" fn(data: *mut u8, len: usize) -> c_int;
Этот тип Callback
совместим с FFI, поэтому вы можете хранить его, передавать между Rust и C и называть его когда угодно. И, конечно, вы можете использовать его в качестве аргумента или типа возвращаемого значения в других объявлениях FFI:
int do_the_thing(uint8_t*data, size_t len, callback cb);
#[no_mangle]
pub extern "C" fn do_the_thing(
data: *const u8, len: usize,
cb: Option<Callback>) -> c_int)
{
//...
}
Помните, что в Rust функции указателя не допускают значения NULL, поэтому, если вы хотите, чтобы C мог чтобы передать NULL
, вы используете Option<fn>
.
Подробнее о FFI в Rust вы можете прочитать в этой главе Rustonomicon .