Swig/python :什么时候需要 SWIG_init() ?

Swig/python : when SWIG_init() is needed?

大家好,感谢您的帮助!

我在尝试导入由 swig 生成的 python 模块时遇到了麻烦。 我有一个包含很少方法的基本库 "example"。 在它旁边,我有一个动态链接到 python 的主程序。 此程序导入生成的模块并调用其中的函数。

如果我的库示例是一个共享的,名为 _example.so,一切正常,我可以将其导入 python。

但是如果我的库是静态的,_example.a,并且链接到主程序,那么我将得到错误 "no module named _example was found",除非我在主要功能。

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

您正在调用的是由 SWIG 生成的 python 包装器加载的本机 python 模块 _example 的 init 函数。对于 python 2,此函数名为 init_example,对于 python 3 it is named PyInit__example.

每个python extension with C or C++都需要这样一个函数,它基本上初始化所有东西并注册模块的名称和所有可用的方法。在您的情况下,SWIG 已为您生成此函数。

静态编译库时必须自己调用此函数的原因很简单,python 包装器示例导入了本机模块 _example,根据 python 约定,它是一个共享对象,您没有编译,因此找不到。

通过调用 SWIG_init,您 "preload" 模块,因此 python 不会尝试重新导入它,因此即使在 python模块路径。

如果您有模块的共享对象,python会在加载共享对象后为您调用此函数,您不必担心。