Можно ли разделить SWIG-модуль для компиляции, но присоединиться к нему при компоновке? - PullRequest
8 голосов
/ 30 марта 2009

Я затронул эту проблему около двух лет назад, когда впервые применил привязки SWIG. Как только мы раскрыли большой объем кода, мы дошли до того, что SWIG будет выводить файлы C ++ настолько большого размера, что компилятор не сможет их обработать. Единственный способ обойти эту проблему - разделить интерфейсы на несколько модулей и скомпилировать их отдельно.

У этого есть несколько недостатков:

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

• Каждый дополнительный модуль увеличивает время, необходимое динамическому компоновщику для загрузки в коде. Я добавил init .py файл, который импортирует все подмодули, так что тот факт, что код разделен на части, прозрачен для пользователя, но что всегда видно, так это длительное время загрузки.

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

Кто-нибудь знает, как я могу добиться этого с помощью SWIG? Я видел некоторый пользовательский код, написанный на Ruby для конкретного проекта, где вывод постобработан, чтобы сделать это возможным, но когда я посмотрел на выполнимость для оболочек Python, это не выглядело так просто.

Ответы [ 2 ]

1 голос
/ 11 января 2017

Я только что сделал эквивалентный хак для библиотеки TCL: я использую несколько модулей SWIG, генерируя несколько файлов .cpp, которые скомпилированы в несколько файлов .o, но компилируют их все в один файл .so, который загружается одним TCL "команда.

Идея состоит в том, чтобы создать верхний модуль swig (Top), который вызывает функции инициализации всех подмодулей (Sub1 и Sub2):

%module Top
%header %{
  extern "C" {
    SWIGEXPORT int Sub1_Init(Tcl_Interp *);
    SWIGEXPORT int Sub2_Init(Tcl_Interp *);
  }
%}
%init %{
    if (Sub1_Init(interp) != TCL_OK) {return TCL_ERROR;}
    if (Sub2_Init(interp) != TCL_OK) {return TCL_ERROR;}
%}

В файлах подмодулей нет ничего особенного. Я получаю файл Top.so, который загружаю из TCL с помощью команды «load ./Top.so"

».

Я не знаю Python, но, вероятно, будет похожим. Возможно, вам придется понять, как загружаются расширения Python.

0 голосов
/ 30 марта 2009

При правильном разбиении модули не обязательно должны иметь те же зависимости, что и остальные - только то, что необходимо для компиляции. Если вы разберетесь с вещами должным образом, у вас могут быть библиотеки без циклических зависимостей. Проблема с использованием нескольких библиотек заключается в том, что по умолчанию SWIG объявляет свой код времени выполнения статически и, как следствие, как проблемы при передаче объектов из одного модуля в другой. Вам необходимо включить общую версию кода выполнения SWIG.

Из документации (ссылка на документацию веб-сайта SWIG не работает):

Функции времени выполнения являются частными для каждый SWIG-сгенерированный модуль. То есть, функции времени выполнения объявлены со «статической» связью и видны только для определенных функций оболочки в этом модуле. Единственная проблема с этот подход заключается в том, что, когда более один модуль SWIG используется в том же приложения, эти модули часто нужны поделиться информацией о типе. Это особенно актуально для программ на C ++, где SWIG должен собирать и делиться информация о наследовании отношения, которые пересекают модуль границы.

Ознакомьтесь с этим разделом в загруженной документации (раздел 16.2 Код среды выполнения SWIG), и он предоставит вам подробную информацию о том, как включить эту функцию, чтобы объекты можно было правильно обрабатывать при передаче из одного модуля в другой. *

FWIW, я не работал с Python SWIG, но сделал Tcl SWIG.

...