Я смотрю на использование python (CPython) в своей программе, чтобы разрешить использование пользовательских сценариев в моей среде и позволить мне использовать pyside, привязки qt для c ++ для создания GUI для моего приложения. Они могут быть эффективно разделены с идеей, что код Python GUI может быть позже скомпилирован для скорости (если это было бы возможно).
Я очень плохо знаком с Python и действительно ищу наиболее эффективный способ создания надежных привязок с абсолютным минимумом дополнительного кода для поддержки, поскольку привязки могут часто меняться по мере развития проекта. Мне это нужно, чтобы классы Python расширяли классы C ++, которые имеют виртуальные.
Я уже изучал PyBindGen, и он слишком часто захлебывается вещами в моей библиотеке, чтобы он был практически полезен.
Любая помощь / совет / ссылки / рабочие процессы, которые вы рекомендуете в этом отношении, были бы очень полезны.
Я знаю только два проекта, которые имеют генераторы автоматического связывания для 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 ++, на случай, если вы решите осмотреться немного дальше:
Теперь они неактивны:
Для полноты также возможно загрузить скомпилированный код C непосредственно в Python без создания формальных привязок. Вы можете сделать это используя FFI
с любым из этих двух модулей Python:
Если вы ищете скорость, я бы тоже проголосовал за 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, если вы об этом попросите, но я думаю, что ссылка, приведенная выше, является хорошей отправной точкой …
Для современного C ++ используйте CLIF (https://github.com/google/clif).
Он не обнаруживает ваш API, вам нужно описать его в терминах Python.
CLIF перекомпилирует ваш заголовок с последним компилятором LLVM / Clang и создаст исходный код C ++ для модуля расширения Python.
Он может понимать сложные структуры данных: def f() -> dict<str, set<int>>
,
Для современного C ++ используйте cppyy: http://cppyy.readthedocs.io/en/latest/
Он основан на Cling, интерпретаторе C ++ для Clang / LLVM. Привязки выполняются во время выполнения, и дополнительный промежуточный язык не требуется. Благодаря Clang он поддерживает C ++ 17.
Специфично для первоначального вопроса об использовании Qt: несколько последних обновлений были сделаны явно для поддержки генерации привязок для всего KDE.
Для скорости: cppyy изначально поддерживается PyPy.
Примечание: я главный автор cppyy.
AFAICT, с C ++ вариантов не так много. Один из старых проектов SWIG; сообщается, что он немного загадочный и неуклюжий, но, поскольку он существует уже давно, он также должен охватывать множество вещей, не связанных с другими проектами. Вы также можете посмотреть на Cython.
SWIG — отличный инструмент, который может делать то, что вы хотите