Swig 封装 C++ 到 Python 在 Mac OS X 中使用默认 Python 而非 Anaconda Python
我正在尝试使用swig将C++函数封装到Python中。我使用了以下命令:
swig -c++ -python helloworld.i
g++ -O2 -fPIC -c hello.cpp
g++ -O2 -fPIC -c helloworld_wrap.cxx -I//anaconda/include/python2.7
g++ -lpython -dynamclib hello.o helloworld_wrap.o -o _helloworld.so
其中,hello.cpp
是包含函数的初始文件,helloworld.i
是封装文件。这些命令创建了一个名为helloworld
的库,但我只能通过默认的Python在/usr/bin/python
中导入它。
如果我尝试通过Anaconda安装的python
导入它,就会出现以下错误:
Fatal Python error: PyThreadState_Get: no current thread
Abort trap: 6
你能告诉我如何用Anaconda的python
来封装代码吗?
我找到了解决方案:使用swig和Anaconda Python时找不到Python.h
在上面的问题中,最上面的回答解释了如何使用disutils
和一个Python中的设置文件来构建库。这真的很有效!:)
接下来,我遇到的问题是如何封装一个简单的类:
我的类代码来自[示例](http://web.mit.edu/svn/src/swig-1.3.25/Examples/python/class/index.html)
/* File : example.h */
class Shape {
public:
Shape() {
nshapes++;
}
virtual ~Shape() {
nshapes--;
};
double x, y;
void move(double dx, double dy);
virtual double area() = 0;
virtual double perimeter() = 0;
static int nshapes;
};
class Circle : public Shape {
private:
double radius;
public:
Circle(double r) : radius(r) { };
virtual double area();
virtual double perimeter();
};
class Square : public Shape {
private:
double width;
public:
Square(double w) : width(w) { };
virtual double area();
virtual double perimeter();
};
我的setup.py
文件:
#setup.py file:
from setuptools import setup, Extension
setup(name='example',
version='0.1',
ext_modules=[Extension('_example', ['example.h', 'example.i'],
swig_opts=['-c++'],
)],
)
我用来封装的代码:
python setup.py build_ext --inplace
错误信息:
running build_ext
building '_example' extension
swigging example.i to example_wrap.cpp
swig -python -c++ -o example_wrap.cpp example.i
error: unknown file type '.h' (from 'example.h')
你能建议一下这里有什么问题吗?我想它没有识别到'.h'文件,但因为这是头文件,我以为可以保持原样。另外,我的setup.py
文件是否正确?我只是想按照简单封装的示例来做,网上似乎没有简单的教程。
我也可以在其他不同的问题上问这个,但我想先在这里继续。
相关文章:
- 暂无相关问题
1 个回答
这是Warren Weckesser在类似的问题中给出的回答。我按照建议使用了setup.py
文件,并把库的路径添加到sys.path
中,效果非常好 :)
在gcc
命令中使用选项-I/Users/myuser/anaconda/include/python2.7
。(假设你使用的是python 2.7,记得把名字改成你实际使用的python版本。)你可以使用命令python-config --cflags
来获取推荐的编译选项:
$ python-config --cflags
-I/Users/myuser/anaconda/include/python2.7 -I/Users/myuser/anaconda/include/python2.7 -fno-strict-aliasing -I/Users/myuser/anaconda/include -arch x86_64 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes
不过,为了构建扩展模块,我建议使用一个简单的设置脚本,比如下面的setup.py
,让distutils
帮你处理所有的编译和链接选项。
# setup.py
from distutils.core import setup, Extension
example_module = Extension('_example', sources=['example_wrap.c', 'example.c'])
setup(name='example', ext_modules=[example_module], py_modules=["example"])
然后你可以运行:
$ swig -python example.i
$ python setup.py build_ext --inplace
(运行setup.py
时,终端会显示编译器命令,看看那些命令。)
distutils
了解SWIG,所以你可以在源文件列表中包含example.i
,而不是example_wrap.c
,这样设置脚本会自动运行swig
:
# setup.py
from distutils.core import setup, Extension
example_module = Extension('_example', sources=['example.c', 'example.i'])
setup(name='example', ext_modules=[example_module], py_modules=["example"])
使用上面的setup.py
版本,你可以通过一个命令来构建扩展模块:
$ python setup.py build_ext --inplace
一旦你构建了扩展模块,就可以在python中使用它:
>>> import example
>>> example.fact(5)
120
如果你不想使用setup.py
脚本,这里有一组对我有效的命令:
$ swig -python example.i
$ gcc -c -I/Users/myuser/anaconda/include/python2.7 example.c example_wrap.c
$ gcc -bundle -undefined dynamic_lookup -L/Users/myuser/anaconda/lib example.o example_wrap.o -o _example.so
注意:我使用的是Mac OS X 10.9.4:
$ gcc --version
Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
Target: x86_64-apple-darwin13.3.0
Thread model: posix