Комментарии 23
Решил посмотреть мнения других в комментариях, а их нет.
Видимо все в крайнем шоке и ужасе.
Память отчистить я постоянно забываю.
Тот еще изврат был, я вам скажу. Подход, предложенный в FFI, пока что выглядит лучше. Но, как говорится, будем посмотреть.
Маленькое замечание: в extern штуковинах, т.е. которые торчат "наружу", предпочтительнее использовать не i32
и подобные, а libc::size_t
, libc::c_int
и другие типы из пакета libc
.
А по скорости не замеряли?
Отличная статья, спасибо. Всех желающих рассказать, что раст это "сложный" язык который с беграундом Java/C#, а уж тем более PHP не осилить буду отправлять к вам.
К слову, чтобы не писать руками "дроп" а использовать растовую магию можно немног схитрить и таскать с собой указатель на структуру. Тогда с помощью mem::forget() можно сделать "утечку", а в destroy
материализовать значение обратно, тогда правильный деструктор рекурсивно вызовется самостоятельно.
Пример такого можно глянуть здесь: https://github.com/nebgnahz/cv-rs/blob/master/src/lib.rs#L124-L142
Метод pack — это аналог вашего FFI, конвертация из Vec в Си-совместимый тип для передачи в FFI. Обратите внимание на строки 124-142 и 163-169. Ваш код побезопаснее, но требует написания ручного рекурсивного вызова деструктора.
Ну и наконец для интеропа самый простой способ это все же JSON, пусть он и не такой быстрый как нативный вызов, но зато минимальное количество бойлерплейта. Правда, вызывать деструктор все равно придется.
P.S. Еще в расте приветствуется не пихать в unsafe-блок больше необходимого. Таким образом, ваш код можно чуть-чуть переписать в виде
#[no_mangle]
pub extern "C" fn parse_arithmetic(s: *const c_char) -> *mut ExpressionFfi {
// todo: error handling
let rust_string = unsafe { CStr::from_ptr(s).to_str().unwrap() };
parse(rust_string).unwrap().convert_to_c()
}
> Всех желающих рассказать, что раст это «сложный» язык который с беграундом Java/C#, а уж тем более PHP не осилить буду отправлять к вам.
Справедливости ради замечу, что Rust все же сложный язык. Cложнее, чем Java или Go в несколько раз.
Fatal error: Uncaught FFI\Exception: FFI API is restricted by «ffi.enable» configuration directive in /var/www/html/plain.local/index.php:10 Stack trace: #0 /var/www/html/plain.local/index.php(10): FFI::cdef() #1 {main} thrown in /var/www/html/plain.local/index.php on line 10
Хотя настройка стоит в true и в phpinfo() это видно. Баг?
FFI: пишем на Rust в PHP-программе