Как вызвать динамическую библиотеку C ++ из Rust? - PullRequest
0 голосов
/ 22 октября 2018

Я хочу вызвать динамическую библиотеку C ++ (* .so) из Rust, но я не хочу собирать ее из Rust.Например,

cc::Build::new()
    .file("src/foo.cc")
    .shared_flag(true)
    .compile("libfoo.so");

В некоторых случаях мне нужно вызывать только несколько функций, а не все функции.Как я могу использовать это?

Ответы [ 2 ]

0 голосов
/ 23 октября 2018

Прежде чем идти дальше, убедитесь, что у вас есть базовое представление о 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 из интерфейса командной строки.
0 голосов
/ 22 октября 2018

По данным веб-сайта Rust , официальная поддержка связи с C ++ отсутствует.Вместо этого вы можете попробовать и использовать библиотеки C.

Существует также тема по этому вопросу на их форуме пользователей , где пользователи предлагают некоторые сторонние проекты, направленные на решение этой проблемы:

  • bindgen - Автоматическое создание FFI для Rust
  • cpp-to-rust -Позволяет использовать библиотеки C ++ от Rust.Основной целью этого проекта является Qt.

Я ими не пользовался, поэтому не могу порекомендовать что-то конкретное или поделиться своим опытом, но удачи:)

...