структура проекта для переноса многих классов С++ в cython в один общий объект

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

Я изучаю cython, пытаясь постепенно обернуть небольшие части библиотеки, которую я уже использую, которая в настоящее время завернута в boost:: python. Я внес небольшой вклад в эту оболочку boost и использую ее в качестве справочника по С++, в то же время я использую Привязки ZeroMQ Python в качестве ссылки на cython.

Мой вопрос касается структуры проекта. Текущая ускоренная версия этой библиотеки компилируется в один .so, и это моя цель. Я быстро понял, что вы не можете напрямую скомпилировать несколько модулей .pyx в один .so. Затем я начал идти по пути определения cppclass в файлах pxd, а соответствующие им классы реализации Python экспортировались в .pxi и пытался включить их в один pyx для компиляции. Сначала это работало, но как только я написал немного больше, я столкнулся с проблемами с конфликтующими несколькими определениями из-за включения pxi в разных местах.

Я хотел бы услышать правильный организационный подход, который решает следующие вопросы и цели:

  • Именование общедоступных классов так же, как cppclass (я делаю это сейчас, имея класс cpp в другом названии pyd и используя импортированное пространство имен для обработки похожих имен, аля Использование cimport для разрешения конфликтов имен)
  • Один .so в качестве скомпилированного вывода (приемлемый подход?)
  • Использую ли я подход pyx с несколькими включениями в основной pyx только для этого, или этот основной pyx должен содержать что-то еще, помимо простого хранения включений?
  • Где централизованно определить константы, которые будут экспортироваться в python?
  • Существует ли предпочтительная структура папок? Прямо сейчас у меня есть все в большом каталоге src под моим setup.py. Смущает такое количество pxi, pxd, pyx файлов.
  • pxi сейчас совсем не нужны? Если нет, нужно ли мне использовать защиту ifndef в стиле cython для обработки множественных включений между разными модулями?
  • Я знаю, что привязки Python ZeroMQ создают несколько модулей и используют пакетный подход, включая их через __init__.py. Это действительно правильный подход к cython?

Для справки, проект, который я практикую для повторной упаковки, называется PyOpenNI (openni). Шаблон, который использует этот проект повышения, состоит в том, чтобы собрать общие объекты в одном месте, а затем определить определение заголовка 1-к-1 с источником, а затем есть огромная оболочка, которая собирает все определения в одном месте. А также добавлена ​​настраиваемая обработка исключений и утилиты.


person jdi    schedule 28.07.2012    source источник
comment
Это возможный подход к части вопроса о связывании различных расширений cython в один общий объект: stackoverflow.com/a/52714500 /5769463   -  person ead    schedule 09.10.2018
comment
@ead Спасибо за ссылку. Довольно интересно! Я мог бы попробовать это с проектом, начатым несколько лет назад, в котором было 10 модулей, которые просто импортировались в основное пространство имен.   -  person jdi    schedule 09.10.2018


Ответы (2)


В ожидании окончательного ответа я продолжал экспериментировать с организацией своего кода. До сих пор работало включение pyx файлов в один pyx для компиляции.

Мой setup.py прост, например:

ext_modules = [
    Extension(
        "openni", 
        ["src/openni.pyx"], 
        language="c++",
        include_dirs=['src/', '/usr/include/ni'],
        libraries=['OpenNI'],
    )
],

Основной openni.pyx выглядит так:

include "constants.pyx"
include "exceptions.pyx"
include "context.pyx"
...

У меня есть общий libopenni.pxd для предоставления внешних модулей, предназначенных только для объявлений, для остальных модулей.

Я называю свои cppclass объявления pxd именем, отличным от определений классов pyx, чтобы избежать конфликта имен:

xncontext.pxd

cdef extern from "XnCppWrapper.h" namespace "xn":
    cdef cppclass Context:
           ...

context.pyx:

from libopenni cimport *
from xncontext cimport Context as c_Context 

cdef class Context:
    cdef c_Context *handle   
        ...
person jdi    schedule 03.08.2012
comment
Можете ли вы указать остальную часть кода, который вы собрали для этой оболочки? У меня похожая проблема с таким же разрешением. Это не приятно, но это работает. - person ibell; 15.05.2014
comment
Привет. Так что это не было чем-то, что попало в публичное репо. Большинство моих последних примеров этой структуры недоступны в сети, но вот один, который я сделал вскоре после этого: github.com/chadmv/plow/tree/master/lib/python/src - person jdi; 15.05.2014
comment
Что я делаю сейчас, так это сохраняю файлы pxi и подключаю подкаталог, чтобы сделать его чистым. И у меня есть только один основной pyx над ним вместе с pxd, который содержит все объявления extern для привязки к C/CPP. - person jdi; 15.05.2014

Ответ на вопрос Есть ли предпочтительная структура папок?

Да, предпочтительной структурой папок для файлов Cython .pyx и .pxd является обращение с ними точно так же, как с файлами .py: по одному на модуль в хорошо организованной структуре пакета. Файлы __init__.pxd могут предоставляться так же, как и файлы __init__.py, для сборки кураторского набора символов для сбора кураторского набора символов из его подмодулей/пакетов для импорта.

Правда, это создает один файл .so для каждого модуля, но эти файлы скрыты в каталоге сборки. То же самое относится и к модулям сборки Python; для каждого из них есть соответствующие файлы .so. Это проблема?

person robertwb    schedule 24.08.2016
comment
Недавно я перешел на подход multi so и импортировал их в единое пространство имен через init.py. - person jdi; 24.08.2016
comment
Я не знал, что init.pxd имеет значение на уровне модуля. - person jdi; 24.08.2016
comment
Отдельные файлы .so для каждого модуля могут быть проблемой, если вы применяете лицензирование (защиту) к этим файлам .so, когда для инициализации лицензирования требуется некоторое время. - person Vlad Frolov; 29.08.2016