Экспорт структур данных C и API C в Python

1

У меня есть источник библиотеки C с C API. Я хочу показать функции и структуры данных C на python, чтобы я мог использовать библиотеку в своих сценариях python.

Существуют более 200+ функции и около 50 структур данных, поэтому было бы предпочтительнее, если бы я мог автоматизировать генерацию кода "клей" между C и Python.

Я сейчас читаю на SWIG, так как это, кажется, путь вперед. Существуют ли другие альтернативы, на которые я должен смотреть (и почему?).

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

Теги:
swig

2 ответа

0
Лучший ответ

Я использовал SWIG 2.x для преобразования довольно сложного API C и C++, и это сэкономило мне много времени.

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

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

После того, как у меня были все функции, я не был полностью доволен результатом. SWIG переводит все ваши функции буквально, но проблема в том, что некоторые идиомы, которые очень распространены в C/C++, выглядят довольно странно в Python. Например, функции, которые имеют выходные аргументы, указанные в качестве указателей, не будут очень Pythonic. Например, рассмотрим эту функцию, которая довольно часто встречается в C/C++:

unsigned int getPath(char* buffer, unsigned int size);

Эта функция принимает буфер и размер и заполняет буфер строкой, возвращая количество байтов на самом деле или 0 в случае ошибки. В Python, чтобы отправить буфер (строка) и размер в качестве аргументов, было бы ужасно странно, поэтому для функций этого стиля я добавил альтернативные версии, которые переводят на более дружественные функции. В этом случае я сделал что-то вроде этого:

const char* getPath();

Реализация этой функции просто передает статический буфер некоторого максимального размера в исходный getPath() и возвращает адрес статического буфера или NULL, если есть ошибка. Отказ от ответственности: я использую компилятор C++, поэтому я могу определить две функции getPath() с разными аргументами. В C вам нужно будет использовать разные имена для каждой функции. SWIG автоматически преобразует char * в строки Python, так что это очень хорошо переводится.

Вместо определения альтернативных функций в C/C++ вы также можете предоставить инструкции SWIG о том, как вы хотите преобразовать определенные функции и их аргументы. Например, SWIG позволяет связать пару аргументов буфера и размера и рассматривать их как один строковый аргумент для переведенной функции. Есть также много удобных переводов, подобных этому.

Что касается учебников, я не нашел ничего полезного вне официальной документации SWIG, что довольно хорошо и имеет раздел, специфичный для Python.

Надеюсь, это поможет.

  • 0
    Спасибо за ваш подробный ответ. В конце концов, я выбрал Cython, потому что хотел создать более Pythonic-интерфейс к библиотеке C (т.е. написать свои собственные классы-обертки).
  • 0
    На самом деле, я сейчас принимаю ваш ответ. После нескольких дней работы с Cython, когда я не получил большой помощи по моим вопросам - я переключился на SWIG - и через 10 минут я скомпилировал свое расширение и был готов его протестировать. Конечно, код Python, сгенерированный SWIG, выглядит неприятно, но я могу с этим смириться!
0

Я не могу комментировать SWIG, но я могу настоятельно рекомендовать Cython (учебник, обертывание библиотек C). Для этого требуется написание кода оболочки вручную, но, по крайней мере, код оболочки - это почти Python, и вам, вероятно, потребуется выполнить некоторую проверку ввода/преобразование и упаковку class, что Cython автоматизирует в значительной степени.

Другой альтернативой является Cython предшественник Pyrex.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню