使用 Swig 和 distutils 为 Python 3 构建扩展
building extension for Python 3 with Swig and distutils
我已经用 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 构建时,我使用几乎完全相同的过程,只是添加了 Python 3 SWIG 标志和 运行 distutils 到 Python 3:
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 扩展时似乎找不到它。有人对我有什么建议吗?我错了吗?
我最终通过更改 XCode 我所链接的 C++ 库的项目设置解决了这个问题。
具体来说,将 "C++ Language Dialect" 设置更改为 "C++ [-std=c++11]",即我在 distutils 的 extra_compile_args 设置中指定的相同版本。以前它是 GNU++11,因此符号不匹配,因为名称空间不匹配(std::vector 与 std::__1::vector)。
有了这个改变,我现在很高兴并成功地从 Python 3.
调用我的 C++ 代码
我真的不明白为什么 在 python 2.7 中工作,因为它使用了所有相同的 distutils 设置,指定了相同的 C++ 版本并且针对同一个 C++ 库的链接。如果有人对此有解释,我很想听听。
我已经用 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 构建时,我使用几乎完全相同的过程,只是添加了 Python 3 SWIG 标志和 运行 distutils 到 Python 3:
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 扩展时似乎找不到它。有人对我有什么建议吗?我错了吗?
我最终通过更改 XCode 我所链接的 C++ 库的项目设置解决了这个问题。
具体来说,将 "C++ Language Dialect" 设置更改为 "C++ [-std=c++11]",即我在 distutils 的 extra_compile_args 设置中指定的相同版本。以前它是 GNU++11,因此符号不匹配,因为名称空间不匹配(std::vector 与 std::__1::vector)。
有了这个改变,我现在很高兴并成功地从 Python 3.
调用我的 C++ 代码我真的不明白为什么 在 python 2.7 中工作,因为它使用了所有相同的 distutils 设置,指定了相同的 C++ 版本并且针对同一个 C++ 库的链接。如果有人对此有解释,我很想听听。