使用Swig和distutils为Python 3构建扩展

3
我用C++构建了一个名为“Checkyrs”的应用程序,现在正在进行一些外部工作,这将使用Checkyrs的大部分功能,但是它是用Python 3构建的(这只是我的业余爱好,所以不需要使用Python 3,但这是我的首选)。为了在Python和C++之间建立接口,我使用了SWIG和Python distutils包。我已经构建了一个动态库,其中包含我从Checkyrs中需要的内容,并且我已经成功地使用我提到的工具构建了一个Python扩展程序(“checkyrsai”)。我已经在Python 2.7中测试过了,并且它完全可用,我需要的所有C++类和函数都可用并且运行正常。但是,我更喜欢使用Python 3,尽管我可以用Python 3构建扩展程序,但我无法成功加载它:
Python 3.4.3 (v3.4.3:9b73f1c3e601, Feb 23 2015, 02:52:03)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import checkyrsai
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/chris/Documents/Programming/eggyolk/checkyrsai.py", line 28, in <module>
    _checkyrsai = swig_import_helper()
  File "/Users/chris/Documents/Programming/eggyolk/checkyrsai.py", line 24, in swig_import_helper
    _mod = imp.load_module('_checkyrsai', fp, pathname, description)
  File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/imp.py", line 243, in load_module
    return load_dynamic(name, filename, file)
ImportError: dlopen(/Users/chris/Documents/Programming/eggyolk/_checkyrsai.so, 2): Symbol not found: __ZN4Game11ExecuteMoveERKSt6vectorI8PositionSaIS1_EE
  Referenced from: /Users/chris/Documents/Programming/eggyolk/_checkyrsai.so
  Expected in: flat namespace
 in /Users/chris/Documents/Programming/eggyolk/_checkyrsai.so

我构建扩展的过程(针对Python 2)如下:

swig -c++ -python checkyrsai.i
python setup.py build_ext --inplace

我的setup.py文件看起来像这样:

from distutils.core import setup, Extension
import os

os.environ["CC"] = "g++"

checkyrsai = Extension('_checkyrsai',
                    sources = ['checkyrsai_wrap.cxx','../checkyrs/checkyrs/ai.cpp'],
                    include_dirs = ['/usr/local/include','../checkyrs/checkyrs'],
                    libraries = ['Checkyrs'],
                    library_dirs = ['../checkyrs/Build/Products/Release/','/usr/local/lib'],
                    extra_compile_args = ['-std=c++11']
                    )


setup (name = 'checkyrs',
       version = '1.0',
       description = 'checkyrs',
       ext_modules = [checkyrsai])

如我之前所说,这个完美地运行。从这个点我可以打开我的Python(2.7)解释器,

import checkyrsai 

我要去玩我的新玩具了。

当尝试为Python 3构建时,我使用几乎完全相同的过程,只需添加用于SWIG的Python 3标志并通过Python 3运行distutils:

swig -c++ -python -py3 checkyrsai.i
python3 setup.py build_ext --inplace

这段程序编译通过并生成了扩展,但当我尝试时...
import checkyrsai

我遇到了ImportError […] Symbol not found的问题,如上所述。

在Python 2和Python 3版本之间,我没有改变我的代码或setup.py脚本。该符号指的是应该在我的libCheckyrs.dylib库中找到的方法。当我使用Python 2.7扩展时,它显然可以成功地使用,但当我为Python 3制作扩展时似乎找不到它。有人能否建议我错在哪里?

1个回答

1
我最终通过更改我链接的C++库的XCode项目设置来解决了这个问题。具体来说,将"C++语言方言"设置更改为"C++ [-std=c++11]",即与我在distutils的extra_compile_args设置中指定的版本相同。之前它是GNU++11,因此符号不匹配,因为命名空间(std::vector vs. std::__1::vector)不匹配。有了这个改变,我现在可以愉快地成功地从Python 3调用我的C++代码了。我真的不明白为什么在python 2.7中它能够工作,因为它使用了完全相同的distutils设置,指定了相同的C++版本并链接到相同的C++ lib。如果有人对此有解释,我很想听听。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接