Можно ли автогенерировать привязки Cython вокруг большой, существующей библиотеки C?

Другими словами: *.h/*.c --[??POSSIBLE??]--> *.pxd/*.pyx

OK. Ive сделал (я надеюсь) достаточно копаться в Интернете - но я думаю, что это хороший вопрос, поэтому я прошу об этом прямо.

Есть несколько связанных вопросов (например, Создание привязок python, какие методы/программы использовать или Обтекание библиотеки C в Python: C, Cython или ctypes?), но которые не совсем суммируют ситуацию, когда я спрашиваю, что, возможно, для более "высокоуровневого" подхода (и специально для существующей библиотеки, а не для создания новых C из python).

Ive получил немного опыта этого сам, обмотав небольшой бит кода перед использованием Cython. Cython получает большие пальцы вверх для скорости и ремонтопригодности. Это нормально в моей книге для небольших/отдельных бит кода, но на этот раз Ive получил немного больше на моей тарелке...

И после первого из трех великих достоинств программиста - я хочу сделать это с минимальными усилиями, насколько это возможно.

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

Это здесь, кажется, единственный реальный намек/примечание о том, как это сделать - но большинство проектов на нем уже не работают, старый или sourceforge. Многие, похоже, работают только на С++ (это C я делаю здесь).

Кто-нибудь все еще использует их? В последнее время? Кто-нибудь получил рабочий процесс или передовую практику для этого? Я просто просто делаю это вручную?

Моя библиотека хорошо определена набором файлов заголовков. Один из них содержит defs всех структур C/типов и другой, содержащий прототипы для всех функций. Но это loooonnnggg...

Спасибо за любые советы.

ОБНОВЛЕНИЕ (25 августа 2015 г.):

Правильно, поэтому за последние несколько месяцев, когда у меня был свободный момент, я попробовал:

  • CFFI (спасибо за @David, указав это) - имеет благородную цель: "вызывать код C из Python без изучения третьего языка: существующие альтернативы требуют, чтобы пользователи изучали специфичный для домена язык (Cython, SWIG) или API (ctypes)", но он не вполне соответствовал законопроекту, поскольку он включал справедливую степень встроенного кода C в фактических файлах python (или загрузке). Это будет довольно ручной процесс для большой библиотеки. Может, я что-то пропустил...

  • SWIG является дедушкой связывания Python и довольно прост. В принципе, хотя это не "руки", как я понимаю, т.е. Вам нужен отдельный файл спецификации. Например, вы должны отредактировать все ваши файлы заголовков C, чтобы указать на создание модуля python с помощью #define SWIG_FILE_WITH_INIT или использовать другие аннотации. SIP имеет такую ​​же проблему. Вы не создаете автогенерацию из заголовков, вы изменяете их, чтобы включить свои собственные директивы и аннотации и создать полный файл спецификации.

  • cwrap - Im на Mac, поэтому я использовал эту версию для clang. https://github.com/geggo/cwrap На самом деле плохой документ - но с использованием источника я, наконец, получил его для запуска и сгенерировал.... пустой .pyx файл из довольно простого заголовка structs. Не очень хорошо.

  • xdress - Это показало обещание. Веб-сайт не работает, поэтому документы фактически кажутся здесь. Theres впечатляющий объем работы, вложенных в него, и это выглядит просто. Но для этого нужны все заголовки llvm (и правильно связанная версия clang). Мне пришлось использовать brew install llvm —with-clang. Существует ветка xdress clang-3.5, но, похоже, она не имеет достаточного количества исправлений. Я попытался нажать на homebrew/версии для более ранней версии clang (install llvm33/llvm34) и создал ее. Во всяком случае, я отвлекаюсь... он отлично подойдет для простого примера, но полученные файлы ctypes для полной библиотеки были довольно искажены и отказались строить. Что-то в AST C- > Python немного пошло...

  • ctypesgen не был тем, с которым я столкнулся в первоначальном поиске. Документация довольно скудная, или вы можете назвать ее кратким. По-видимому, за последние 4 года не было сделано много работы (и люди, задающие вопросы по списку проблем, если разработчики когда-либо будут продвигать проект). Ive попробовал запустить его, но, к сожалению, похоже, что это похоже на то, что я подозреваю/похоже на проблемы с компилятором Clang cdefs.h с использованием _attribute_. Я пробовал такие вещи, как -std=c11, но безрезультатно.

В заключение, из всех рассмотренных Ive, я думаю, что xdress стал ближе всего к полностью автоматизированной генерации привязок python. Он отлично работал для простых приведенных примеров, но не мог обрабатывать более сложные существующие заголовки библиотек со всеми сложностями форвардных объявлений, перечисляемыми типами, указателями void... Кажется, хорошо спроектированный и (на время) хорошо поддерживаемый проект, так что возможно, каким-то образом обойти эти проблемы, если кто-то снова возьмет его.

Тем не менее, остается вопрос: у кого-нибудь есть надежная инструментальная цепочка для автоматического создания оболочек python из заголовков C? Я считаю, что реальность всегда должна быть немного ручной работы, и для этого CFFI выглядит самым "современным" подходом (один из лучших обзоров/сравнений, с которыми я столкнулся, - здесь), но он всегда включает специально отредактированную версию cdef() любых файлов заголовков (например, Использование CFFI на Python и исключение системных заголовков),

Ответы

Ответ 1

Я считаю, что ctypesgen отлично подходит для автогенерации. Я использую его только с одним или двумя модулями python, которые, я надеюсь, открою исходный код, и до сих пор я доволен. Вот быстрый пример использования zlib, но я также просто попробовал его с несколькими другими библиотеками:

(Редактирование: я знаю, что вы упомянули, что ctypesgen имеет проблемы на Mac, поэтому, возможно, кому-то нужно настроить его для работы с OSX - у меня нет OSX дома или я бы попробовал.)

Получить ctypesgen:

git clone https://github.com/davidjamesca/ctypesgen.git

Запустите короткую script, чтобы вызвать ctypesgen (замените zlib info другой библиотекой):

import os                           

ZLIB_INC_DIR = "/usr/include"       
ZLIB_LIB_DIR = "/usr/lib/x86_64-linux-gnu"       
ZLIB_LIB = "libz.so"       
ZLIB_HEADERS = "/usr/include/zlib.h"       

# Set location of ctypesgen.py                                      
ctypesgen_path = 'ctypesgen/ctypesgen.py'                                       

wrapper_filename = 'zlib.py'                                                 
cmd = "LD_LIBRARY_PATH={} {} -I {} -L {} -l {} {} -o {}".format(             
ZLIB_LIB_DIR, ctypesgen_path, ZLIB_INC_DIR, ZLIB_LIB_DIR, ZLIB_LIB,      
ZLIB_HEADERS, wrapper_filename)                                        

print(cmd)
os.system(cmd)                                                             

Пример использования:

python
>>> import zlib
>>> zlib.compress("asdfasdfasdfasdfasdf")
'x\x9cK,NIKD\xc3\x00T\xfb\x08\x17'