Какой самый быстрый способ создать привязку Python к библиотеке C или C ++?
(Я использую Windows, если это имеет значение.)
Вы должны взглянуть на Boost.Python . Вот краткое введение, взятое с их сайта:
Boost Python Library - это фреймворк для взаимодействия Python и C ++. Он позволяет вам быстро и беспрепятственно представлять функции и объекты классов C ++ для Python и наоборот, не используя специальных инструментов - только ваш компилятор C ++. Он предназначен для незаметного переноса интерфейсов C ++, поэтому вам не нужно вообще менять код C ++, чтобы обернуть его, что делает Boost.Python идеальным для предоставления сторонним библиотекам Python. Использование библиотеки передовых методов метапрограммирования упрощает ее синтаксис для пользователей, так что код переноса выглядит как своего рода декларативный язык определения интерфейса (IDL).
Модуль ctypes является частью стандартной библиотеки и поэтому более стабилен и широко доступен, чем swig , что всегда вызывало у меня проблемы .
В случае ctypes вам необходимо удовлетворить любую зависимость времени компиляции от python, и ваша привязка будет работать на любом питоне, имеющем ctypes, а не только на том, с которым он был скомпилирован.
Предположим, у вас есть простой пример класса C ++, с которым вы хотите поговорить в файле с именем foo.cpp:
Поскольку ctypes может общаться только с функциями C, вам нужно предоставить тех, кто объявляет их как внешние "C"
Далее вы должны скомпилировать это в общую библиотеку
И, наконец, вы должны написать свою оболочку Python (например, в fooWrapper.py)
Если у вас есть это, вы можете назвать это как
источник
extern "C" { __declspec(dllexport) Foo* Foo_new(){ return new Foo(); } __declspec(dllexport) void Foo_bar(Foo* foo){ foo->bar(); } }
Foo_delete
функцию и вызвав ее либо из деструктора Python, либо поместив объект в ресурс .Самый быстрый способ сделать это - использовать SWIG .
Пример из учебника SWIG :
Файл интерфейса:
Сборка модуля Python в Unix:
Применение:
Обратите внимание, что у вас должен быть python-dev. Также в некоторых системах заголовочные файлы python будут находиться в /usr/include/python2.7 в зависимости от того, как вы его установили.
Из учебника:
источник
Я начал свое путешествие с привязки Python <-> C ++ с этой страницы с целью связать высокоуровневые типы данных (многомерные векторы STL со списками Python) :-)
Испытав решения, основанные как на ctypes, так и на boost.python (и не будучи инженером-программистом), я обнаружил, что они сложны, когда требуется связывание типов данных высокого уровня, в то время как я обнаружил SWIG для таких случаев гораздо проще.
Таким образом, в этом примере используется SWIG, и он был протестирован в Linux (но SWIG доступен и также широко используется в Windows).
Цель состоит в том, чтобы сделать функцию C ++ доступной для Python, которая принимает матрицу в форме 2D-вектора STL и возвращает среднее значение каждой строки (как 1D-вектор STL).
Код на C ++ ("code.cpp") выглядит следующим образом:
Эквивалентный заголовок ("code.h"):
Сначала мы скомпилируем код C ++ для создания объектного файла:
Затем мы определяем файл определения интерфейса SWIG ("code.i") для наших функций C ++.
Используя SWIG, мы генерируем исходный код интерфейса C ++ из файла определения интерфейса SWIG.
Наконец, мы скомпилировали сгенерированный исходный файл интерфейса C ++ и соединили все вместе, чтобы создать общую библиотеку, которая напрямую импортируется Python (имеет значение «_»):
Теперь мы можем использовать функцию в скриптах Python:
источник
Существует также
pybind11
, которая похожа на облегченную версию Boost.Python и совместима со всеми современными компиляторами C ++:https://pybind11.readthedocs.io/en/latest/
источник
Pytorch
pytorch.org/tutorials/advanced/cpp_extension.html Также полностью работает наVS Community
WindowsПроверьте Pyrex или Cython . Это Python-подобные языки для взаимодействия между C / C ++ и Python.
источник
Для современного C ++ используйте cppyy: http://cppyy.readthedocs.io/en/latest/
Он основан на Cling, интерпретаторе C ++ для Clang / LLVM. Привязки выполняются во время выполнения, и дополнительный промежуточный язык не требуется. Благодаря Clang он поддерживает C ++ 17.
Установите его используя pip:
Для небольших проектов просто загрузите соответствующую библиотеку и интересующие вас заголовки. Например, возьмите код из примера ctypes, который приведен ниже, но разделите его на разделы заголовка и кода:
Скомпилируйте это:
и использовать это:
Большие проекты поддерживаются автоматической загрузкой подготовленной информации об отражении и фрагментов cmake для их создания, так что пользователи установленных пакетов могут просто запустить:
Благодаря LLVM возможны расширенные функции, такие как автоматическое создание шаблона. Чтобы продолжить пример:
Примечание: я автор cppyy.
источник
swig
,ctypes
илиboost.python
. Вместо того, чтобы писать код, чтобы заставить python работать с вашим кодом на c ++ ... python делает тяжелую работу, чтобы понять c ++. Предполагая, что это действительно работает.В этой статье, утверждающей, что Python - это все, что нужно ученому , в основном говорится: Первый прототип всего на Python. Затем, когда вам нужно ускорить часть, используйте SWIG и переведите эту часть на C.
источник
Я никогда не использовал это, но я слышал хорошие вещи о ctypes . Если вы пытаетесь использовать его с C ++, обязательно избегайте искажения имени через
extern "C"
. Спасибо за комментарий, Флориан Бёш.источник
Я думаю, что CFFI для Python может быть вариантом.
http://cffi.readthedocs.org/en/release-0.7/
источник
Вопрос в том, как вызвать функцию C из Python, если я правильно понял. Тогда лучшим выбором будет Ctypes (кстати, переносимый во всех вариантах Python).
Для подробного руководства вы можете обратиться к моей статье в блоге .
источник
Один из официальных документов Python содержит подробности о расширении Python с использованием C / C ++ . Даже без использования SWIG , это довольно просто и отлично работает на Windows.
источник
Определенно, Cython - это путь, если только вы не планируете писать обертки Java, в этом случае SWIG может быть предпочтительнее.
Я рекомендую использовать
runcython
утилиту командной строки, она делает процесс использования Cython чрезвычайно простым. Если вам нужно передать структурированные данные в C ++, посмотрите библиотеку Protobuf от Google, это очень удобно.Вот минимальные примеры, которые я сделал, которые используют оба инструмента:
https://github.com/nicodjimenez/python2cpp
Надеюсь, что это может быть полезной отправной точкой.
источник
Сначала вы должны решить, какова ваша конкретная цель. Официальная документация Python по расширению и внедрению интерпретатора Python была упомянута выше, я могу добавить хороший обзор бинарных расширений . Варианты использования можно разделить на 3 категории:
Чтобы дать более широкую перспективу для других заинтересованных лиц, и поскольку ваш первоначальный вопрос немного расплывчатый («к библиотеке C или C ++»), я думаю, что эта информация может быть вам интересна. По ссылке выше вы можете прочитать о недостатках использования бинарных расширений и их альтернатив.
Помимо других предложенных ответов, если вы хотите ускоритель, вы можете попробовать Numba . Он работает «путем генерации оптимизированного машинного кода с использованием инфраструктуры компилятора LLVM во время импорта, во время выполнения или статически (с помощью включенного инструмента pycc)».
источник
Мне нравится cppyy, он позволяет легко расширять Python с помощью кода C ++, значительно увеличивая производительность при необходимости.
Это мощный и, честно говоря, очень простой в использовании,
здесь приведен пример того, как вы можете создать пустой массив и передать его функции-члену класса в C ++.
cppyy_test.py
buffer.h
Вы также можете очень легко создать модуль Python (с помощью CMake), таким образом вы всегда будете избегать перекомпиляции кода C ++.
источник
Пример минимального запуска pybind11
Ранее pybind11 упоминался по адресу https://stackoverflow.com/a/38542539/895245, но я хотел бы привести здесь конкретный пример использования и дальнейшее обсуждение реализации.
В общем, я настоятельно рекомендую pybind11, потому что он действительно прост в использовании: вы просто включаете заголовок, а затем pybind11 использует магию шаблонов для проверки класса C ++, который вы хотите представить в Python, и делает это прозрачно.
Недостаток этого шаблона в том, что он замедляет компиляцию, сразу добавляя несколько секунд к любому файлу, использующему pybind11, см., Например, исследование, выполненное по этой проблеме . PyTorch соглашается .
Вот минимальный исполняемый пример, чтобы дать вам представление о том, насколько классным является pybind11:
class_test.cpp
class_test_main.py
Скомпилируйте и запустите:
В этом примере показано, как pybind11 позволяет без особых усилий представлять
ClassTest
класс C ++ для Python! Компиляция создает файл с именем,class_test.cpython-36m-x86_64-linux-gnu.so
которыйclass_test_main.py
автоматически выбирается в качестве точки определения дляclass_test
собственного модуля.Возможно, осознание того, насколько это круто, только впитывается, если вы попытаетесь сделать то же самое вручную с помощью собственного Python API, посмотрите, например, на этот пример, который имеет примерно в 10 раз больше кода: https://github.com /cirosantilli/python-cheat/blob/4f676f62e87810582ad53b2fb426b74eae52aad5/py_from_c/pure.c В этом примере вы можете видеть, как код C должен больно и явно определять класс Python побитово со всей информацией, которую он содержит (члены, методы, далее) метаданные ...). Смотрите также:
pybind11 утверждает, что он похож на тот,
Boost.Python
который упоминался на https://stackoverflow.com/a/145436/895245, но более минималистичен, потому что он освобожден от раздувания пребывания внутри проекта Boost:pybind11 также является единственной не родной альтернативой, выделенной текущей документацией по связыванию Microsoft Python C по адресу: https://docs.microsoft.com/en-us/visualstudio/python/working-with-c-cpp-python-in- visual-studio? view = vs-2019 ( архив ).
Протестировано на Ubuntu 18.04, pybind11 2.0.1, Python 3.6.8, GCC 7.4.0.
источник