Создавать привязки python, какие методы/программы использовать
Я смотрю на использование python (CPython) в своей программе, чтобы позволить сценарию пользователя в моей среде и разрешить мне использовать pyside, привязки qt для С++ для создания графического интерфейса для моего приложения. Они могут быть эффективно разделены идеей о том, что код python GUI может быть позже скомпилирован для скорости (если это будет возможно).
Я очень новичок в python, и я действительно ищу наиболее эффективный способ создания сплошных привязок с абсолютным минимумом дополнительного кода для поддержки, поскольку привязки, вероятно, будут часто меняться по мере развития проекта. Мне это нужно, чтобы классы python расширяли классы С++, у которых есть виртуальные машины.
Я уже посмотрел на PyBindGen, и он слишком часто вторгается в вещи в моей библиотеке, чтобы это было практически полезно.
Любая помощь/советы/ссылки/рабочие процессы, которые вы рекомендуете в этом отношении, будут очень полезны.
Ответы
Ответ 1
Я знаю только два проекта, чтобы иметь генераторы автоматической привязки для 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++, на случай, если вы решите осмотреться немного дальше:
- SWIG - как вы уже знаете
- Boost.Python - это то, что мы обычно используем здесь - довольно хорошо структурировано
- Cython - очень аккуратный синтаксис, близкий к Python - они утверждают, что намного быстрее, чем Boost.Python
- SIP - не очень распространен, но он есть
- pybind11 - Синтаксис похож на Boost.Python, компактная реализация благодаря C++ 11.
Теперь они неактивны:
- PyBindGen - утверждает, что он самый быстрый, но неактивен с 21 мая 2017 года, предыдущий выпуск 2014 года - в настоящее время поддерживается на github (https://github.com/gjcarneiro/pybindgen/releases)
- ECS: Python - неактивен с 6 декабря 2014 г. (версия 2.8), перемещен в github (https://github.com/MarcusTomlinson/ECS-Python)
- PyCXX - C++ средства для облегчения написания расширений Python - неактивны? Последний выпуск был v7.0.2 23 апреля 2017 года
- CLIF - CLIF обеспечивает общую основу для создания генераторов обертки C++ для различных языков - неактивно? Не так много операций репо (всего 14 коммитов)
Для полноты также возможно загрузить скомпилированный код C непосредственно в Python без создания формальных привязок. Вы можете сделать это, используя FFI
с любым из этих двух модулей Python:
- ctypes - это родной для Python и не требует установки внешнего модуля.
- cffi - это новая упаковка, вдохновленная аналогичным дизайном Lua JIT.
Ответ 2
Если вы ищете скорость, я определенно проголосую за Cython. Насколько я знаю о других способах интерфейса С++ с Python, Cython не так уж тяжело поддерживать/обновлять по сравнению с другими инструментами привязки, относящимися к усилению "текучести рабочего процесса". (Китонизированный код утверждает, что он будет таким же быстрым, как чистый C, или не далеко от него, что также делает его очень интересным).
Во всяком случае, существует несколько хороших API для подключения кода на Python с С++ (Boost.Python,...), но я думаю, что все они приведут к необходимости разоблачения методов непосредственно в исходном коде на С++ (вы, ребята, говорите если я ошибаюсь или неточен).
С другой стороны, Cython предоставит вам возможность поддерживать ваш С++ API (GUI или что-то еще...), строго отделенную от источников экспозиции (так называемые расширения .pyx). Окончательный рабочий процесс:
С++ API = > Компиляция в качестве общего объекта = > Расширения Cython (импорт и отображение возможностей С++) = > Компиляция расширений (-ов) = > Использование расширения (расширение добавляется к вашему пути python).
Хорошей новостью является то, что вам нужно будет поддерживать только изменяющиеся части вашего пула файлов .pyx, связанных с меняющимися функциями С++ (среди тех, которые требуют, чтобы их открывали). Сначала это своего рода инвестиция, но, по моему опыту, после того, как этот рабочий процесс настроен, довольно просто сделать все, чтобы все это получилось по сложности.
Теперь о вашей необходимости расширять классы, которые имеют виртуальные и переопределять их с Python (если я правильно понял, что вы имели в виду). Это выполнимо. Еще раз, не так прямо, но вы должны посмотреть на этот поток.
Плохая новость: в этом конкретном случае вам нужно будет создать дополнительные С++-адаптеры/интерфейсы, чтобы включить вызов родительского метода, если расширенный python не переопределяет данный родительский метод. (Обратите внимание, что переопределение открытого на С++ метода, виртуального или нет, из python является заменой функции, но абсолютно не эквивалентно переопределению).
Hummf, теперь, когда я читаю себя, это выглядит немного запутанным. Надеюсь, это по-прежнему полезно.
Я могу быть более конкретным в отношении рабочего процесса, с которым вам придется иметь дело, если вы выберете опцию Cython, если вы попросите меня, но я думаю, что связанная с этим нить неплохая отправная точка...
Ответ 3
Для современного С++ используйте CLIF (https://github.com/google/clif).
Он не обнаруживает ваш API, вам нужно описать его в терминах Python.
CLIF перекомпилит ваш заголовок с помощью последнего компилятора LLVM/Clang и создаст исходный код С++ для модуля расширения Python.
Он может понимать сложные структуры данных: def f() -> dict<str, set<int>>
.
Ответ 4
Для современных C++ используйте cppyy: http://cppyy.readthedocs.io/en/latest/
Он основан на Cling, интерпретаторе C++ для Clang/LLVM. Привязки выполняются во время выполнения, и дополнительный промежуточный язык не требуется. Благодаря Clang он поддерживает C++ 17.
Специфично для первоначального вопроса об использовании Qt: несколько последних обновлений были сделаны явно для поддержки генерации привязок для всего KDE.
Для скорости: cppyy изначально поддерживается PyPy.
Примечание: я главный автор cppyy.
Ответ 5
AFAICT, есть не так много вариантов с С++. Один из старых проектов - SWIG; он, как сообщается, был немного загадочным и неуклюжим, но поскольку он был долгое время, он должен также охватывать множество вещей, которые не обрабатываются другими проектами. Вы также можете посмотреть Cython.
Ответ 6
SWIG - отличный инструмент, который может делать то, что вы хотите.
http://sourceforge.net/projects/swig/
Ответ 7
Вы можете использовать Scapix Language Bridge для автоматической генерации привязок Python непосредственно из заголовков C++ как части сборки.
Вызовите scapix_bridge_headers()
в вашем CMake, чтобы получить список заголовков C++ с классами, которые вы хотите экспортировать, а затем создайте свой проект с помощью cmake -DSCAPIX_BRIDGE=python
. Смотрите полный пример.
Отказ от ответственности: я являюсь автором Scapix Language Bridge.