python - 使用 distutils 编译 Cython 代码时出现问题

标签 python gcc cython cythonize

我正在尝试编译 Cython 代码并将其用作 Python 模块。我关注了Cython's basic tutorial 。我已经制作了文件helloword.pyx:

print "Hello World"

我已经制作了setup.py:

from distutils.core import setup
from Cython.Build import cythonize

setup(
    ext_modules = cythonize("helloworld.pyx")
)

然后运行:

python setup.py build_ext --inplace

但不幸的是发生了错误:

running build_ext
building 'helloworld' extension
gcc -pthread -Wno-unused-result -Wsign-compare -DDYNAMIC_ANNOTATIONS_ENABLED=1 -DNDEBUG -O2 -g -pipe -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fstack-protector --param=ssp-buffer-size=4 -g -O2 -g -pipe -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fstack-protector --param=ssp-buffer-size=4 -I/usr/include/ncursesw -fPIC -I/usr/include/python3.5m -c helloworld.c -o build/temp.linux-x86_64-3.5/helloworld.o
gcc -pthread -shared -Wl,--as-needed -Wl,-z,relro -Wl,-O1 -Wl,--build-id -Wl,--enable-new-dtags build/temp.linux-x86_64-3.5/helloworld.o -L/usr/lib64 -lpython3.5m -o /home/dima/Projects/AntennaModeling/test/helloworld.cpython-35m-x86_64-linux-gnu.so
/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-mageia-linux-gnu/5.4.0/../../../libpython3.5m.so when searching for -lpython3.5m
/bin/ld: skipping incompatible /lib/libpython3.5m.so when searching for -lpython3.5m
/bin/ld: skipping incompatible /usr/lib/libpython3.5m.so when searching for -lpython3.5m
/bin/ld: cannot find -lpython3.5m
collect2: error: command ld failed with exit status 1
error: command 'gcc' failed with exit status 1

看来gcc对python3.5库不满意。我尝试使用以下命令在没有 distutils 的情况下进行编译:

cython -a helloworld.pyx
gcc -shared -pthread -fPIC -fwrapv -O2 -Wall -fno-strict-aliasing -I/usr/include/python3.5m -o helloworld.so helloworld.c

而且它成功了。据了解,我可以从Python解释器导入helloworld。但我不知道如何使用 distutils 编译 Cython 代码。我尝试使用 extra_compile_args 传递相同的标志,但没有成功。

更新: 它发现 gcc 找不到 python 的 64 位库,因此尝试显式显示库目录。所以我改变了setup.py

from distutils.core import setup
from distutils.extension import Extension
from Cython.Build import cythonize

extensions = [
        Extension("helloworld", ["helloworld.pyx"],
        library_dirs = ['/usr/lib64']),
        ]
setup(
    name = 'Hello world app',
    ext_modules = cythonize(extensions),
)

仍然是相同的输出

running build_ext
building 'helloworld' extension
gcc -pthread -Wno-unused-result -Wsign-compare -DDYNAMIC_ANNOTATIONS_ENABLED=1 -DNDEBUG -O2 -g -pipe -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fstack-protector --param=ssp-buffer-size=4 -g -O2 -g -pipe -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fstack-protector --param=ssp-buffer-size=4 -I/usr/include/ncursesw -fPIC -I/usr/include/python3.5m -c helloworld.c -o build/temp.linux-x86_64-3.5/helloworld.o
gcc -pthread -shared -Wl,--as-needed -Wl,-z,relro -Wl,-O1 -Wl,--build-id -Wl,--enable-new-dtags build/temp.linux-x86_64-3.5/helloworld.o -L/usr/lib64 -L/usr/lib64 -lpython3.5m -o /home/dima/Projects/AntennaModeling/test/helloworld.cpython-35m-x86_64-linux-gnu.so
/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-mageia-linux-gnu/5.4.0/../../../libpython3.5m.so when searching for -lpython3.5m
/bin/ld: skipping incompatible /lib/libpython3.5m.so when searching for -lpython3.5m
/bin/ld: skipping incompatible /usr/lib/libpython3.5m.so when searching for -lpython3.5m
/bin/ld: cannot find -lpython3.5m
collect2: error: command ld failed with exit status 1
error: command 'gcc' failed with exit status 1

最佳答案

通常,链接器会搜索名称为 libXXX.so 的库。而不是libXXX.so.1.0 (如果不成功,则针对名称为 libXXX.a 的库)。通常libXXX.solibXXX.so.Y.0 的符号链接(symbolic link)这才是真正的图书馆。

您可以通过使用-Wl,--verbose调用链接命令来观察链接器的工作情况,例如:

gcc -Wl,--verbose -pthread -shared -Wl,--as-needed -Wl,-z,relro -Wl,-O1 -Wl,--build-id -Wl,--enable-new-dtags build/temp.linux-x86_64-3.5/helloworld.o -L/usr/lib64 -lpython3.5m -o /home/dima/Projects/AntennaModeling/test/helloworld.cpython-35m-x86_64-linux-gnu.so

你会看到类似的内容:

...
attempt to open /usr/lib64/libpython3.5m.so failed
...

所以有两个选择:

A:引入符号链接(symbolic link)/usr/lib64/libpython3.5m.so在您的系统上。

或较少侵入性 B:添加 libraries=[':libpython3.5m.so.1.0']到您的扩展定义:

extensions = [
        Extension("helloworld", ["helloworld.pyx"],
        library_dirs = ['/usr/lib64']),
        libraries=[':libpython3.5m.so.1.0']
        ]

现在链接命令看起来应该有点不同:

 gcc ... -L/usr/lib64 -l:libpython3.5m.so.1.0 ...

链接器将寻找 libpython3.5m.so.1.0不仅是libpython3.5m.so仍然由 distutils 提供。

关于python - 使用 distutils 编译 Cython 代码时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46299339/

相关文章:

python - 如何更改搜索结果CKAN中的默认排序顺序?

python - 使用 win32com 模块的 Python 2.7 中的 Qualcomm QPST 自动化服务器

c++ - GCC对纯函数的优化

c - 如何将 Python 字符串列表转换为 C 语言 wchar_t 数组?

python - 使用 jinja2 仅显示 URL 域的最佳方式

python - 使用日期列删除所有表中早于时间段的所有数据

c - 网络链接,海湾合作委员会。对 rtnl_open 的 undefined reference

c - 为什么 stdarg.h 中的第一个参数是寄存器?

python - 将 Pandas 数据框中的行和上一行与数百万行进行比较的最快方法

python - Cython:存储指针时 Python/C++ 之间的内存所有权问题