【发布时间】:2015-11-23 19:47:04
【问题描述】:
我在 OSX 上,试图用 distutils 的 setup.py 编译一个 C 中的共享库(使用 ctypes 在 python 中使用)。我是 distutils 的新手,但是当我要编译的共享库 (libreboundx.so) 依赖于另一个共享库 (librebound.so) 时,我遇到了问题。明确地,在 modify_orbits_direct.c 我有
#include "rebound.h"
rebound.h在/Users/dt/rebound/src/目录下,rebound.h中的所有函数都在/Users/dt/rebound/的共享库librebound.so中。
与 cc 的链接看起来像。
cc -fPIC -shared reboundx.o -L/Users/dt/rebound -lrebound -o libreboundx.so
更新:这种情况看起来与第二节末尾的示例完全相同。 3https://docs.python.org/2/extending/building.html。我已经更新了我的 setup.py 来模仿那个:
libreboundxmodule = Extension('libreboundx',
sources = [ 'src/reboundx.c',
'src/modify_orbits_direct.c'],
include_dirs = ['src', '/Users/dt/rebound/src'],
extra_compile_args=['-fstrict-aliasing', '-O3','-std=c99','-march=native', '-D_GNU_SOURCE', '-fPIC'],
library_dirs=['/Users/dt/rebound'],
libraries=['rebound'],
)
运行时安装良好
pip install -e ./
构建输出:
You are using pip version 7.0.3, however version 7.1.2 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
Obtaining file:///Users/dtamayo/Documents/workspace/reboundx
Installing collected packages: reboundx
Running setup.py develop for reboundx
Successfully installed reboundx-1.0
但是当我尝试时
import reboundx
在 Python 中,我得到一个 OSError: dlopen(libreboundx.so, 10): Symbol not found: _reb_boundary_particle_is_in_box,这是另一个库 (librebound.so) 中的一个函数,它甚至没有在代码中被调用对于 libreboundx.so。
如果我将共享库与上面的 cc 命令链接,一切正常,我可以在 C 中使用共享库 libreboundx.so 非常好。如果我尝试使用相同的 libreboundx.so,我使用 cc 命令进行编译并把它贴在 setup.py 放它的地方,然后尝试在 python 中导入反弹x,我反而得到了
OSError: dlopen(/Users/dtamayo/Documents/workspace/reboundx/reboundx/../libreboundx.so, 10): Library not loaded: librebound.so
引用自:/Users/dtamayo/Documents/workspace/reboundx/libreboundx.so 原因:找不到图片
这可能是一个 rpath 问题,在运行时 libreboundx.so 不知道去哪里寻找 librebound.so?
【问题讨论】:
-
libraries=['librebound']看起来很可疑。这不应包含lib-前缀,而应仅包含rebound。你也没有链接到-llibrebound,而是-lrebound。除此之外,你能提供构建输出吗? -
我已将其添加到问题中。我在库中使用“librebound”或“rebound”得到完全相同的行为/输出(这表明出了点问题!)。另外,我尝试在底部的 install_requires 中添加“反弹”。这给出了“要求已经满足(使用 --upgrade 升级):在 /Users/dtamayo/Documents/workspace/rebound 中反弹(来自反弹x==1.0)”,但是当我在 Python 中导入时出现同样的错误。
-
在 OS X 上,
otool -D显示 lib 的install_name,install_name_tool -id将更改它。如果您想要相对于加载模块的路径,请使用@loader_path标记。使用otool -L列出依赖关系,并使用install_name_tool -change更改它们。也可以设置-rpath依赖搜索路径;这可以使用@loader_path作为相对路径。Extension类有一个rpath参数,但这个类确实不适合构建通用共享模块(尤其是在 Windows 上,如果这很重要的话)。可以直接调用ccompiler.new_compiler执行gcc。 -
因为无论如何你都需要一个编译器,从总体上看,如果你改用CFFI的API接口而不是ctypes,你的生活可能会更简单。
-
顺便说一句,我从未使用过 OS X,所以请以我的建议为起点。参考dyld man page、OS X ABI Mach-O File Format Reference,以及Mach-O Binaries上的这篇文章。