В PHP 7.4 появится FFI, т.е. можно подключать библиотеки на языке C (или, например, Rust) напрямую, без необходимости писать целый extension и разбираться в его многочисленных нюансах.  Идея реализации FFI в PHP 7.4 была взята из LuaJIT и Python, а именно: в язык встроен парсер, который понимает декларации функций, структур и т.д. языка Си. По факту туда можно подсунуть всё содержимое заголовочного файла и сразу начать использовать его. Пример:  Подключать чьи-то готовые либы — это просто и весело, но хочется и что-то своё написать. Например, нужно быстро распарсить какой-то файл, и результаты парсинга использовать из php. Из трех системных языков (C, C++, Rust) лично я выбираю последний. Причина проста: у меня не хватит компетенций, чтобы сходу написать безопасную по памяти программу на C или С++. Rust сложноват, но в этом смысле выглядит надёжнее. Компилятор сразу указывает тебе, где ты неправ. Почти невозможно добиться Undefined Behavior. Disclaimer: я не являюсь системным программистом, поэтому дальнейшее используйте на свой страх и риск. Давайте для начала напишем что-то совсем простое, простую функцию для складывания чисел. Просто для тренировки. А потом перейдем к более сложной задаче. Создаем проект как библиотеку  cargo new hellofromrust --lib и указываем в cargo.toml, что это динамическая библиотека (dylib)  Сама функция на Расте выглядит так ну т.е. обычная функция, только к ней добавлено пара магических слов no_mangle и extern "C" Далее, делаем cargo build, чтобы получить so-файл (под Линуксом) Можно использовать из php: Складывать числа просто. Функция принимает целые аргументы по значению, и возвращает новое целое число. А что если нужно использовать строки? А что если функция возвращает ссылку на дерево элементов? А как использовать специфические конструкции Раста в сигнатуре функций? Эти вопросы меня замучили, поэтому я написал парсер арифметических выражений на Расте. И решил использовать его из PHP для изучения всех нюансов. Полный код проекта здесь: simple-rust-arithmetic-parser. Кстати, туда же я положил docker образ, в котором есть PHP (скомпилированный с FFI), Rust, Cbindgen и т.д. Всё, что нужно для запуска. Парсер, если рассматривать чистый язык Раст, делает следующее: берет строку вида "100500*(2+35)-2*5" и преобразовывает в выражение-дерево expression.rs: это Растовый enum, а в Расте, как известно, enum — это не просто набор констант, но к ним можно еще привязать значение. Здесь если тип узла Expression::Value, то к нему записано целое число, например 100500. Для узла типа Add будем хранить также две ссылки (Box) на выражения-операнды этого сложения.
 Парсер я написал довольно быстро, несмотря на ограниченное знание Rust, а вот с FFI пришлось помучиться. Если в C строки — это указатель на тип char *, т.е. указатель на массив символов, заканчивающихся на \0, то в Расте это совсем другой тип. Поэтому необходимо преобразовать входную строку в тип &str следующим образом:  Подробнее про CStr Это всё полбеды. Настоящая проблема в том, что ни Растовых енумов, ни безопасных ссылок типа Box в языке C нет. Поэтому пришлось сделать отдельную структуру ExpressionFfi для хранения дерева выражений в C-стиле, т.е. через struct, union и простые указатели (ffi.rs). Ну и метод для преобразования в нее: Box::into_raw превращает тип Box в сырой "сишный" указатель В итоге функция, которую мы будем экспортировать в PHP, выглядит так: Здесь куча unwrap(), что означает "паникуй при любой ошибке". В нормальном продакшен коде конечно же ошибки нужно обрабатывать нормально и передавать ошибку как часть возврата С-функции. Ну и мы видим здесь вынужденный блок unsafe, без него бы ничего не скомпилировалось. К сожалению, в этом месте программы компилятор Rust не может отвечать за безопасность памяти. Это понятно и естественно. На стыке Rust и C такое будет всегда. Однако во всех других местах всё абсолютно контролируемо и безопасно. Фуф, ну вроде всё, можно компилировать. Но вообще-то есть еще один нюанс: надо еще надо написать заголовочные конструкции, чтобы PHP понимал сигнатуры функций и типов. К счастью, в Раст есть удобная тулза cbindgen. Она автоматически ищет в коде на Раст конструкции, которые помечены extern "C", repr(С) и т.д. и генерит заголовочный файлы Мне пришлось немного помучиться с настройками cbindgen, они у меня получились такие (cbindgen.toml): Не уверен, что я четко понимаю все нюансы, но это работает ) Пример запуска: Результат будет такой: Итак,  сгенерировали h-файл, компилируем библиотеку cargo build и можно написать наш php код. Код просто выводит рекурсивной функцией printExpression на экран то, что распаршено нашей Rust-библиотекой Ну вот и всё, спасибо за внимание. Хрен там был "всё". Память надо еще очистить. Раст не может применить свою магию за пределами Раст-кода. Добавляем еще одну функцию destroy Box::from_raw(expression); — преобразовывает сырой указатель в тип Box, а так как результат этого преобразования никем не используется, то происходит автоматическое уничтожение памяти при выходе из скоупа. Не забываем сбилдить и сгенерить заголовочный файл. и в php добавляем вызов нашей функции Вот теперь точно всё. Если вы хотите дополнить или рассказать, что я где-то был не прав, please feel free to comment. Репозиторий с полным примером находится по ссылке: [https://github.com/anton-okolelov/simple-rust-arithmetic-parser] Больше полезного можно найти на telegram-канале о разработке "Cross Join", где мы обсуждаем базы данных, языки программирования и всё на свете! Go-тимлид, веду канал https://t.me/crossjoin