Прежде чем идти дальше, убедитесь, что у вас есть базовое представление о Rust FFI (интерфейс сторонней функции) .
В Rust легко вызвать C, но трудно вызвать C ++.
Чтобы вызывать функции C в Rust, вам просто нужно обернуть их с помощью extern
, выполнить некоторое базовое приведение типов и иногда unsafe
.
Для вызова функций C ++, так как Rust делаетне обладая встроенными знаниями о возможностях C ++, вам, возможно, придется много переводить вручную.Например, вот часть документации из Rust-Qt :
Многие вещи напрямую переведены с C ++ на Rust:
- Примитивные типыотображаются на примитивные типы Rust (например,
bool
), а типы, предоставляемые libc crate (например, libc::c_int
). - Числовые типы фиксированного размера (например,
int8_t
или qint8
) отображаются на Rustтипы фиксированного размера (например, i8
). - Указатели, ссылки и значения отображаются на соответствующие типы Rust.
- Пространства имен C ++ отображаются на подмодули Rust.
- Классы C ++и структуры отображаются на структуры ржавчины.Это также относится ко всем экземплярам шаблонных классов, встречающихся в API библиотеки, включая шаблонные классы зависимостей.
- Свободные функции сопоставляются с свободными функциями.
- Методы класса сопоставляются с реализациями структур.
- Деструкторы отображаются на реализации
Drop
и CppDeletable
. - Типы указателей на функции отображаются на эквивалентное представление Rust.Указатели на функции со ссылками или значениями классов не поддерживаются.
static_cast
и dynamic_cast
доступны в Rust через соответствующие черты.
Имена идентификаторов Rust модифицируются в соответствии с Rustсоглашения об именах.
Когда прямой перевод невозможен:
- Содержимое каждого включаемого файла библиотеки C ++ помещается в отдельный подмодуль.
- Перегрузка методаэмулируется с упаковкой аргументов в кортеж и созданием черты, описывающей кортежи, приемлемые для каждого метода.Методы с аргументами по умолчанию обрабатываются одинаково.
- Одиночное наследование транслируется в реализацию
Deref
и DerefMut
, позволяющую вызывать методы базового класса для производных объектов.Если принудительных приведений недостаточно, static_cast
следует использовать для преобразования из производного в базовый класс. - Методы получения и установки создаются для каждого поля открытого класса.
Не реализованопока, но планируется:
- Перевести C ++
typedef
s в псевдонимы типа Rust. - Реализовать операторные черты для структур, основанных на методах операторов C ++ ( issue ).Операторы в настоящее время представлены как обычные функции с префиксом
op_
. - Реализация отладочных и отображаемых черт для структур, если на стороне C ++ существуют применимые методы.
- Реализация черт итераторов для коллекций.
- API создания подклассов ( выпуск ).
- Предоставление доступа к публичным переменным класса ( выпуск ).
- Обеспечение преобразования из перечислений в int иback (используется в Qt API).
- Поддержка типов C ++, вложенных в типы шаблонов, например
Class1<T>::Class2
.
Не планируется поддерживать:
- Расширенное использование шаблонов, например типы с целочисленными аргументами шаблона.
- Частичные специализации шаблона.
- Методы и функции шаблона.
Мое предложение заключается в том, чтобы обернутьБиблиотека C ++ в качестве библиотеки C, затем назовите ее официальным способом FFI или используйте rust-bindgen для автоматического выполнения переноса.
Если вы все еще хотите вызывать C ++ в Rust, rustcxx кажется удобнымol.
Что касается связывания библиотек, все довольно просто:
- Поместите библиотеку в пути поиска вашей системной библиотеки, например
/usr/lib
или /usr/local/lib/
, убедитесь, что она может бытьнайдено ldconfig -p
. - Или используйте переменную среды
LD_LIBRARY_PATH
, чтобы указать путь к вашей библиотеке при запуске cargo
из интерфейса командной строки.