Подтвердить что ты не робот

Python: SWIG vs ctypes

В python, при каких обстоятельствах SWIG лучше выбрать, чем ctypes для вызова точек входа в разделяемых библиотеках? Предположим, что у вас еще нет файлов интерфейса SWIG.

Каковы показатели производительности двух?

4b9b3361

Ответ 1

SWIG генерирует (довольно уродливый) код C или С++. Это простое использование для простых функций (вещи, которые могут быть переведены напрямую) и достаточно просты в использовании для более сложных функций (таких как функции с выходными параметрами, для которых требуется дополнительный шаг перевода для представления на Python). Для более эффективного взаимодействия вы часто необходимо записать биты C как часть файла интерфейса. Для чего угодно, кроме простого использования, вам нужно будет узнать о CPython и о том, как он представляет объекты - не сложно, а что-то иметь в виду.

ctypes позволяет вам напрямую обращаться к функциям C, структурам и другим данным и загружать произвольные разделяемые библиотеки. Вам не нужно писать C для этого, но вам нужно понять, как работает C. Возможно, вы можете утверждать, что обратная сторона SWIG: он не генерирует код, и он не требует компилятора во время выполнения, но для чего угодно, кроме простого использования, он требует, чтобы вы понимали, как такие вещи, как типы данных C, управление памятью и выравнивание. Вам также необходимо вручную или автоматически перевести C-структуры, союзы и массивы в эквивалентную структуру данных ctypes, включая правильную компоновку памяти.

Вероятно, что в чистом исполнении SWIG быстрее, чем ctypes, потому что управление вокруг фактической работы выполняется в C в compiletime, а не в Python во время выполнения. Однако, если вы не взаимодействуете с множеством различных функций C, но каждый раз несколько раз, маловероятно, что накладные расходы будут действительно заметными.

Во время разработки ctypes имеет значительно более низкую стоимость запуска: вам не нужно изучать файлы интерфейса, вам не нужно создавать файлы .c и компилировать их, вам не нужно проверять и отключать предупреждения. Вы можете просто вскочить и начать использовать одну C-функцию с минимальными усилиями, а затем расширить ее до большего. И вы можете протестировать и попробовать прямо в интерпретаторе Python. Обертка большого количества кода несколько утомительна, хотя есть попытки сделать это проще (например, ctypes-configure.)

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

Ответ 2

У меня богатый опыт использования swig. SWIG утверждает, что это быстрое решение для упаковки вещей. Но в реальной жизни...


Минусы:

SWIG разработан как общий, для всех и для более 20 языков. Как правило, это приводит к недостаткам:
- нужна конфигурация (шаблоны SWIG.i), иногда это сложно,
- отсутствие лечения некоторых особых случаев (см. далее свойства python),
- отсутствие производительности для некоторых языков.

Python cons:

1) Непоследовательность стиля кода. С++ и python имеют очень разные стили кода (это очевидно, конечно), возможности swig для создания целевого кода более pythonish очень ограничены. В качестве примера можно создать свойства от геттеров и сеттеров. См. этот q & a

2) Отсутствие широкого сообщества. У Swig есть хорошая документация. Но если кто-то поймал то, чего нет в документации, вообще нет информации. Никакие блоги и поисковые запросы не помогают. Поэтому в таких случаях нужно сильно разбить код сгенерированного SWIG... Это ужасно, я могу сказать...

Procs:

  • В простых случаях это очень быстро, легко и прямо.

  • Если вы создали файлы интерфейса swig один раз, вы можете обернуть этот код на С++ любым другим 20 + языками (!!!).

  • Одна большая проблема в SWIG - это производительность. Поскольку версия 2.0.04 SWIG включает флаг "-builtin", который делает SWIG еще быстрее, чем другие автоматизированные способы упаковки. По крайней мере некоторые тесты показывают это.


Когда использовать US SWIG?

Итак, я заключил для себя два случая, когда swig хорошо использовать:

2) Если нужно обернуть код С++ для нескольких языков. Или, если возможно, может быть время, когда нужно распространять код для нескольких языков. Использование SWIG в этом случае является надежным.

1) Если вам нужно быстро обернуть только несколько функций из некоторой библиотеки С++ для конечного использования.


Живой опыт

Обновить:
Прошло полтора года, так как мы сделали конверсию нашей библиотеки с помощью SWIG.

Сначала мы сделали версию python. Было несколько моментов, когда мы столкнулись с проблемами с SWIG - это правда. Но сейчас мы расширили нашу библиотеку до Java и .NET. Итак, у нас есть 3 языка с 1 SWIG. И я могу сказать, что SWIG rock с точки зрения экономии времени.

Обновление 2:
Это два года, когда мы используем SWIG для этой библиотеки. SWIG интегрирован в нашу систему сборки. Недавно у нас было большое изменение API в С++. SWIG работал отлично. Единственное, что нам нужно было сделать, это добавить несколько% переименований в .i файлы, чтобы наш CppCamelStyleFunctions() теперь looks_more_pythonish в python. Сначала меня беспокоили некоторые проблемы, которые могли возникнуть, но ничего не случилось. Это было потрясающе. Всего несколько изменений и все, что распространяется на 3 языках. Теперь я уверен, что это хорошее решение для использования SWIG в нашем случае.

Обновление 3:
Это уже 3 года, мы используем SWIG для нашей библиотеки. Основное изменение: часть python полностью переписана в чистом питоне. Причина в том, что python используется для большинства приложений нашей библиотеки. Даже если чистая версия python работает медленнее, чем С++-упаковка, пользователям удобнее работать с чистым python, не борясь с родными библиотеками.

SWIG по-прежнему используется для версий .NET и Java.

Главный вопрос: "Мы бы использовали SWIG для python, если бы мы начали проект с самого начала?". Мы будем! SWIG позволил нам быстро распространить наш продукт на многие языки. Он работал в течение определенного периода времени, что давало нам возможность лучше понять требования наших пользователей.

Ответ 3

CTypes очень круто и намного проще, чем SWIG, но имеет тот недостаток, что плохой или злонамеренно написанный код на Python может привести к краху процесса python. Вы также должны рассмотреть boost python. ИМХО это на самом деле проще, чем swig, давая вам больше контроля над финальным интерфейсом python. Если вы все равно используете С++, вы также не добавляете в свой микс какие-либо другие языки.

Ответ 4

По моему опыту, ctypes имеет большой недостаток: когда что-то пойдет не так (и оно неизменно будет для любых сложных интерфейсов), это ад для отладки.

Проблема заключается в том, что большая часть вашего стека скрывается с помощью ctypes/ffi magic, и нет простого способа определить, как вы попали в конкретную точку, и почему значения параметров являются тем, чем они являются.

Ответ 5

Вы также можете использовать Pyrex, который может действовать как клей между высокоуровневым кодом Python и низкоуровневым C-кодом. lxml записывается, например, в Pyrex.

Ответ 6

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

Ctypes тоже хорош, но, как говорили другие, он не делает С++.

Насколько велика библиотека, которую вы пытаетесь обернуть? Как быстро изменяется кодовая база? Любые другие вопросы обслуживания? Все это, вероятно, повлияет на выбор лучшего способа записи привязок Python.

Ответ 7

ctypes отлично, но не обрабатывает классы С++. Я также обнаружил, что ctypes примерно на 10% медленнее, чем прямая привязка C, но это будет сильно зависеть от того, что вы вызываете.

Если вы собираетесь использовать ctypes, обязательно проверьте проекты Pyglet и Pyopengl, которые имеют массовые примеры привязок ctype.

Ответ 8

Просто хотел добавить еще несколько соображений, о которых я еще не упоминал. [РЕДАКТИРОВАТЬ: Ой, не видел ответа Майка Стейдера]

Если вы хотите попробовать использовать реализацию не Cpython (например, PyPy, IronPython или Jython), то ctypes - это единственный путь. PyPy не позволяет писать C-расширения, поэтому исключает pyrex/cython и Boost.python. По той же причине ctypes является единственным механизмом, который будет работать для IronPython и (в конечном счете, как только они заработают) jython.

Как уже упоминалось, компиляции не требуется. Это означает, что если выйдет новая версия .dll или .so, вы можете просто ее загрузить и загрузить эту новую версию. Пока ни один из интерфейсов не изменился, это сокращение замены.

Ответ 9

Что-то, о чем следует помнить, заключается в том, что SWIG нацелен только на реализацию CPython. Поскольку ctypes также поддерживается реализациями PyPy и IronPython, возможно, стоит написать свои модули с помощью ctypes для совместимости с более широкой экосистемой Python.

Ответ 10

Я обнаружил, что SWIG будет немного раздутым в своем подходе (в общем, не только Python), и его трудно реализовать без необходимости пересекать больную точку написания кода Python с явным мышлением, чтобы быть SWIG-совместимым, а не написав чистый хорошо написанный код Python. Это, ИМХО, гораздо более простой процесс записи привязок C к С++ (если используется С++), а затем использовать ctypes для взаимодействия с любым слоем C.

Если библиотека, с которой вы взаимодействуете, имеет интерфейс C как часть библиотеки, другое преимущество ctypes заключается в том, что вам не нужно компилировать отдельную библиотеку связывания с python для доступа к сторонним библиотекам. Это особенно хорошо при разработке решения pure-python, которое позволяет избежать проблем с межплатформенной компиляцией (для сторонних библиотек, предлагаемых на разрозненных платформах). Необходимость встраивать скомпилированный код в пакет, который вы хотите развернуть на чем-то вроде PyPi, кросс-платформенным способом - боль; одним из моих самых раздражающих моментов в отношении пакетов Python с использованием SWIG или базового явного кода C является их общая недоступность кросс-платформенной. Поэтому рассмотрите это, если вы работаете с кросс-платформенными доступными сторонними библиотеками и разрабатываете решение python вокруг них.

Как пример реального мира, рассмотрим PyGTK. Это (я считаю) использует SWIG для генерации кода C для взаимодействия с вызовами GTK C. Я использовал это в течение короткого времени только для того, чтобы найти настоящую боль, чтобы настроить и использовать, с причудливыми нечетными ошибками, если вы не делали ничего в правильном порядке при настройке и просто в общем. Это был такой неприятный опыт, и когда я взглянул на определения interace, предоставленные GTK в Интернете, я понял, что простое упражнение было бы написать переводчик интерфейса для интерфейса ctypes python. Был создан проект под названием PyGGI, и в один день я смог переписать PyGTK как гораздо более функциональный и полезный продукт, который полностью соответствует интерфейсам GT-C-объектно-ориентированного интерфейса. И это не требует компиляции C-кода, что делает его кросс-платформенным. (Я был фактически после взаимодействия с webkitgtk, который не является настолько кросс-платформенным). Я также могу легко развернуть PyGGI на любой платформе, поддерживающей GTK.