Вопрос

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

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

Это было полезно?

Решение

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

ctypes позволяет вам напрямую обращаться к функциям, структурам и другим данным языка Си, а также загружать произвольные разделяемые библиотеки.Вам не нужно писать никакой C для этого, но вам нужно понимать, как C работает.Вы могли бы возразить, что это обратная сторона ГЛОТКА:он не генерирует код и не требует компилятора во время выполнения, но для чего угодно, кроме простого использования, требуется, чтобы вы понимали, как работают такие вещи, как типы данных C, приведение, управление памятью и выравнивание.Вам также необходимо вручную или автоматически преобразовать структуры C, объединения и массивы в эквивалентную структуру данных ctypes, включая правильное расположение памяти.

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

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

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

Другие советы

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


Минусы:

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

Минусы Python:

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

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

Плюсы:

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

  • Если вы один раз создавали файлы интерфейса swig, вы можете перенести этот код C ++ на ЛЮБОЙ из более чем 20 языков (!!!).

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


Когда ИСПОЛЬЗОВАТЬ SWIG?

Итак, я сделал для себя вывод о двух случаях, когда глоток хорош в употреблении:

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

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


Живой опыт

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top