Swig / python: когда нужен SWIG_init ()? - PullRequest
0 голосов
/ 03 июля 2018

Привет всем и спасибо за попытку помочь мне!

Я сталкиваюсь с проблемой при попытке импортировать модуль python, сгенерированный swig. У меня есть базовый «пример» библиотеки, содержащий несколько методов. Рядом с ним у меня есть основная программа, динамически связанная с Python. Эта программа импортирует сгенерированный модуль и вызывает в нем функцию.

Если мой пример библиотеки является общим, с именем _example.so, все работает отлично, и я могу импортировать его в python.

Но если моя библиотека статическая, _example.a и связана с основной программой, у меня будет ошибка "модуль с именем _example не найден", если я не добавлю вызов SWIG_init () в основную функцию.

Что именно делает SWIG_init () и когда мне его использовать? Мне это кажется довольно странным, потому что в документации никогда не говорится, чтобы сделать такой вызов.

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

Вот мой основной файл:

#include "Python.h"
#include <iostream>

#if PY_VERSION_HEX >= 0x03000000
#  define SWIG_init    PyInit__example

#else
#  define SWIG_init    init_example

#endif

#ifdef __cplusplus
extern "C"
#endif

#if PY_VERSION_HEX >= 0x03000000
PyObject*
#else
void
#endif
SWIG_init(void);

int main (int arc, char** argv)
{
    Py_Initialize();
    SWIG_init(); // needed only using the statically linked version of example ?    
    PyRun_SimpleString("print \"Hello world from Python !\"");

    PyRun_SimpleString("import sys");
    PyRun_SimpleString("sys.path.append(\"/path/to/my/module\")");

    PyRun_SimpleString("import example");
    PyRun_SimpleString("a = example.Example()");
    PyRun_SimpleString("print a.fact(5)");
}

Вот как все это генерируется:

swig -c++ -python example.i

g++ -fpic -c example.cpp example_wrap.cxx -I/include/python2.7 -lstdc++
ar rvs libexample.a example.o example_wrap.o
// to generate dynamic instead of static : g++ -shared example.o example_wrap.o -o _example.so 

g++ main.cpp -I/include/python2.7 libexample.a -lstdc++ -L/lib/python -lpython2.7 -o main

1 Ответ

0 голосов
/ 03 июля 2018

То, что вы называете, является функцией инициализации собственного модуля Python _example, который загружается сгенерированной оболочкой Python SWIG. Для python 2 эта функция называется init_example, а для python 3 она называется PyInit__example.

Каждое расширение python с C или C ++ нуждается в такой функции, оно в основном инициализирует все и регистрирует имя модуля и все доступные для него методы. В вашем случае SWIG сгенерировал эту функцию для вас.

Причина, по которой вам нужно вызывать эту функцию самостоятельно, когда вы статически компилируете библиотеку, заключается в том, что пример оболочки Python импортирует собственный модуль _example, который в соответствии с соглашением Python является общим объектом, который вы не компилировали, и который, таким образом, является не найден.

Вызывая SWIG_init, вы «предварительно загружаете» модуль, поэтому python не пытается его повторно импортировать, поэтому он работает, даже если на пути к модулю python нет общего объекта.

Если у вас есть общий объект для вашего модуля, python вызовет эту функцию для вас после загрузки общего объекта, и вам не нужно об этом беспокоиться.

...