我有一个c ++程序,我正在尝试包装/转换为Cython。它使用特定的库,由于某种原因,不会导致导入的工作模块。顺便说一句,有一个工作的c ++程序。这是setup.py:
ext_modules = [
Extension(
name="libnmfpy",
sources=["interface/nmf_lib.pyx"],
include_dirs = ["../src/", numpy.get_include()],
libraries=["nmf","mpi_cxx","mpi","m"],
library_dirs=["../build/Linux/bin.release","/usr/local/lib/","/usr/lib"],
language="c++",)
]
setup(
name = 'libnmfpy',
cmdclass = {'build_ext': build_ext},
ext_modules = ext_modules,
)
我应该提到它似乎是导致问题的libnmf。 libnmf的第一个版本会导致此脚本生成此错误:
/usr/bin/ld: ../build/Linux/bin.release/libnmf.a(nmf.o): relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC
../build/Linux/bin.release/libnmf.a: could not read symbols: Bad value
collect2: error: ld returned 1 exit status
当我使用-fPIC重建libnmf时,setup会生成一个libnmfpy.so,但是当我在另一个脚本中导入它时,我会得到上面提到的未定义符号:
Traceback (most recent call last):
File "test.py", line 1, in <module>
import libnmfpy
ImportError: $path/cython/libnmfpy.so: undefined symbol: _ZN4elem6lapack3SVDEiiPdiS1_
如果它会有所帮助,这是我的搜索建议:
nm libnmfpy.so | grep _ZN4elem6lapack3SVDEiiPdiS1_
U _ZN4elem6lapack3SVDEiiPdiS1_
nm ../build/Linux/bin.release/libnmf.a | grep _ZN4elem6lapack3SVDEiiPdiS1_
U _ZN4elem6lapack3SVDEiiPdiS1_
我猜错误的原因是什么。我看一下我认为是libnmf所构建的有问题的库:
nm $another_path/lib/libelemental.a | grep _ZN4elem6lapack3SVDEiiPdiS1_
0000000000005290 T _ZN4elem6lapack3SVDEiiPdiS1_
我对图书馆和链接器不太熟悉,所以任何帮助都会受到赞赏。感谢
编辑:一点点挖掘让我意识到了什么。我应该注意Mac OS X和Linux之间的区别吗?我为之工作的人写的最初报告没有像这样的构建错误
答案 0 :(得分:3)
您应该使用nm -C
来解开符号。它看起来像是混合静态和共享库,这通常不是一个好主意。此外,gcc的链接器是一个通道链接器,这意味着库标志的顺序很重要。您希望以反向依赖顺序列出库。换句话说,如果a依赖于b,则b必须出现在链接器标志中的a之前。
答案 1 :(得分:1)
我无法尝试重新创建您的设置,然后在我的设置上测试解决方案,因为我没有您的来源,但在我看来,当您使用fpic重新编译libnmf时,它是在动态链接之前重新编译的,而之前它是静态链接的。
如果我的猜测是正确的,那么您可以尝试:
-fPIC
和-static
再次编译libnmf。 "elemental"
添加到libraries
列表 - 这将使链接器也获取该lib。 你应该注意到方法#1通常被认为不太理想,但正如我所说,它可能是最初以这种方式编译的。但是,#2可能需要更多的工作,因为如果还有其他需要的库,你也必须找到并添加它们。