Генерация привязок Python, какие методы / программы использовать

Я смотрю на использование python (CPython) в своей программе, чтобы разрешить использование пользовательских сценариев в моей среде и позволить мне использовать pyside, привязки qt для c ++ для создания GUI для моего приложения. Они могут быть эффективно разделены с идеей, что код Python GUI может быть позже скомпилирован для скорости (если это было бы возможно).

Я очень плохо знаком с Python и действительно ищу наиболее эффективный способ создания надежных привязок с абсолютным минимумом дополнительного кода для поддержки, поскольку привязки могут часто меняться по мере развития проекта. Мне это нужно, чтобы классы Python расширяли классы C ++, которые имеют виртуальные.

Я уже изучал PyBindGen, и он слишком часто захлебывается вещами в моей библиотеке, чтобы он был практически полезен.

Любая помощь / совет / ссылки / рабочие процессы, которые вы рекомендуете в этом отношении, были бы очень полезны.

13

Решение

Я знаю только два проекта, которые имеют генераторы автоматического связывания для C ++. Первый — это SWIG. Как уже сказал какой-то другой ответ, это немного старый стиль, но он работает. Второй — Boost.Python — сам по себе он не генерирует привязки автоматически, но вы можете использовать Boost.Pyste сделать это для вас. Требуется GCC-XML для анализа исходного кода и записи привязок Boost.Python. Оба варианта поддерживают виртуальные методы в C ++, которые могут быть перегружены из Python.

Тем не менее, я должен дополнить это, обычно, когда вы связываете, вы не слепо привязываете все, что у вас есть в C ++, к Python — если вы сделаете это так, вы не получите очень питонического чувства со стороны Python. Вместо этого вы проектируете, как бы вы хотели, чтобы ваша библиотека использовалась в Python самым питонным из возможных способов, а затем вы возвращаетесь назад и видите, как соединить ее с вашим кодом C ++, используя одну из возможных библиотек привязки. Например, вместо того, чтобы иметь дело с std::vectorс, вы бы предпочли, чтобы ваши вызовы библиотеки обрабатывали списки Python или итерации. Если ваша библиотека C ++ получает std::mapВы хотите, чтобы это обрабатывалось с помощью словарей Python. Если это массив, может быть numpy.ndarray было бы удобнее. И так далее…

Тем не менее, вы по-прежнему можете создавать свои привязки так, чтобы ваше обслуживание было минимальным.

Вот список других оболочек Python / C ++, на случай, если вы решите осмотреться немного дальше:

  1. SWIG — как ты уже знаешь
  2. Boost.Python — это то, что мы обычно используем здесь — довольно хорошо структурированы
  3. Cython — очень аккуратный синтаксис, близкий к Python — они утверждают, что намного быстрее, чем Boost.Python
  4. ГЛОТОК — не очень распространено, но оно есть
  5. pybind11 — Синтаксис похож на Boost.Python, компактная реализация благодаря C ++ 11.

Теперь они неактивны:

  1. PyBindGen — утверждает, что самый быстрый, но неактивный с 21 мая 2017 года, предыдущий выпуск 2014 года — в настоящее время поддерживается на github (https://github.com/gjcarneiro/pybindgen/releases)
  2. ECS: Pythonнеактивный с 6 декабря 2014 г. (версия 2.8) перешел на github (https://github.com/MarcusTomlinson/ECS-Python)
  3. PyCXX — Средства C ++ для облегчения написания расширений Python — неактивный? Последний выпуск был v7.0.2 23 апреля 2017
  4. CLIF — CLIF обеспечивает общую основу для создания генераторов оболочки C ++ для различных языков — неактивный? Не большая активность по репо (только 14 коммитов)

Для полноты также возможно загрузить скомпилированный код C непосредственно в Python без создания формальных привязок. Вы можете сделать это используя FFI
с любым из этих двух модулей Python:

  1. ctypes — Это родной для Python и не требует установки внешнего модуля.
  2. cffi — Это новая упаковка, вдохновленная аналогичным дизайном Lua JIT.
13

Другие решения

Если вы ищете скорость, я бы тоже проголосовал за Cython. Насколько мне известно о других способах взаимодействия C ++ с Python, Cython не так уж и сложен в обслуживании / обновлении по сравнению с другими инструментами связывания, что касается увеличения «плавности рабочего процесса». (Cythonized код утверждает, что он так же быстр, как чистый C, или недалеко от того, что также делает его очень интересным).

В любом случае, есть несколько хороших API для соединения кода Python с C ++ (Boost.Python, …), но я думаю, что все они приведут к необходимости выставлять методы непосредственно в исходном коде C ++ (ребята, скажите, если я я не прав или неточен).

С другой стороны, Cython даст вам возможность держать ваш C ++ API (GUI или любой другой …) строго отделенным от источников воздействия (так называемых расширений .pyx). Окончательный рабочий процесс будет:

C ++ API => Компиляция как общий объект => Расширение (я) Cython (импорт и демонстрация возможностей C ++) => Компиляция расширения (ей) => Использование расширения (расширение, которое будет добавлено к вашему пути Python).

Хорошая новость заключается в том, что вам придется поддерживать только изменяющиеся части вашего пула файлов .pyx, связанные с развивающимися функциями C ++ (среди тех, которые должны быть представлены). Поначалу это своего рода инвестиция, но, по моему опыту, когда этот рабочий процесс настроен, довольно просто усложнить весь процесс.

Теперь о том, что вам нужно расширять классы, имеющие виртуалы, и переопределять их из Python (если я правильно понял, что вы имели в виду). Это выполнимо. Еще раз, не так прямо, но вы должны взглянуть на это нить.

Плохая новость: в этом конкретном случае вам нужно будет создать несколько дополнительных адаптеров / интерфейсов C ++, чтобы разрешить вызов родительского метода, если расширенный Python не перекрывает метод данного родителя. (Обратите внимание, что переопределение открытого метода C ++, виртуального или нет, из python является заменой функции, но абсолютно не эквивалентно переопределению).

Hummf, теперь, когда я читаю себя обратно, это выглядит немного запутанным. Надеюсь, это все еще полезно.

Я могу более конкретно рассказать о рабочем процессе, с которым вам придется иметь дело, если вы выберете опцию Cython, если вы об этом попросите, но я думаю, что ссылка, приведенная выше, является хорошей отправной точкой …

2

Для современного C ++ используйте CLIF (https://github.com/google/clif).
Он не обнаруживает ваш API, вам нужно описать его в терминах Python.

CLIF перекомпилирует ваш заголовок с последним компилятором LLVM / Clang и создаст исходный код C ++ для модуля расширения Python.

Он может понимать сложные структуры данных: def f() -> dict<str, set<int>>,

2

Для современного C ++ используйте cppyy: http://cppyy.readthedocs.io/en/latest/

Он основан на Cling, интерпретаторе C ++ для Clang / LLVM. Привязки выполняются во время выполнения, и дополнительный промежуточный язык не требуется. Благодаря Clang он поддерживает C ++ 17.

Специфично для первоначального вопроса об использовании Qt: несколько последних обновлений были сделаны явно для поддержки генерации привязок для всего KDE.

Для скорости: cppyy изначально поддерживается PyPy.

Примечание: я главный автор cppyy.

2

AFAICT, с C ++ вариантов не так много. Один из старых проектов SWIG; сообщается, что он немного загадочный и неуклюжий, но, поскольку он существует уже давно, он также должен охватывать множество вещей, не связанных с другими проектами. Вы также можете посмотреть на Cython.

0

SWIG — отличный инструмент, который может делать то, что вы хотите

http://sourceforge.net/projects/swig/

0
По вопросам рекламы [email protected]