Swig 封装 C++ 到 Python 在 Mac OS X 中使用默认 Python 而非 Anaconda Python

0 投票
1 回答
1107 浏览
提问于 2025-05-10 21:40

我正在尝试使用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 个回答

0

这是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

撰写回答