Можете ли вы запустить код ржавчины из библиотеки c, вызываемой из ржавчины?
Я просмотрел ржавый интерфейс внешних функций и успешно (и счастливо) может вызывать библиотеку c из моего кода ржавчины.
Однако я не могу найти никаких подробностей о том, как зарегистрировать обратный вызов для вызова кода ржавчины, из области c-кода.
Возможно ли это?
В качестве оправдания для "почему бы вам это сделать?"; в частности, я смотрю на встраивание lua или python в приложение с ржавчиной и выставляя скрипты-api для скриптов, которые выполняются во встроенной среде выполнения.
Вызов этих элементов будет выглядеть следующим образом:
- Загрузка основных ресурсов ржавчины
- Приложение использует ffi для инициализации времени выполнения скриптов.
- Приложение связывает локальные функции ржавчины с C-обратными вызовами
- Приложение вызывает ffi, чтобы связать C-обратные вызовы с уровнем сценариев
- Приложение работает ~
- Периодически ffi используется для запуска исполняемого файла сценариев для выполнения блоков байт-кода
- Код сценария выполняет различную тривиальную логику и вызывает связанные ручки
- Связанные дескрипторы ссылаются на код c
- Связанный c-код вызывает локальный код ржавчины
Все эти шаги, за исключением выделенных жирным, мне удалось получить работу, и я проделал какую-то тривиальную работу с помощью планировщика, который C-callbacks запускает команды "запустите меня" в очередь и когда управление возвращается в область ржавчины, приложение запрашивает очередь и запускает в ней команды...
... но это немного неудобно со стороны сценариев, потому что это означает множественные вложенные обратные вызовы async, а точка слоя сценариев - это упростить код, который должен войти в слой сценариев.
Ответы
Ответ 1
Да, вы можете передать функцию обратного вызова из Rust в C и вызвать ее там.
Главное знать, что вам нужно определить функцию с атрибутом extern "C".
Неподтвержденный пример (здесь нет компилятора Rust):
Сторона ржавчины:
extern "C" fn callback(a:i32) {
println!("I'm called from C with value {0}", a);
}
#[link(name = "mylib")]
extern {
fn register_callback(cb: extern "C" fn(i32)) -> i32;
}
fn main() {
unsafe {
register_callback(callback);
}
...
}
C сторона:
typedef void (*rust_callback)(int32_t);
rust_callback cb;
int32_t register_callback(rust_callback callback) {
cb = callback;
return 1;
}
void thread() {
// do sth
cb(xyz);
}