我有一个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时,安装程​​序会生成libnmfpy.so,但是当我将其导入另一个脚本时,将得到上述 undefined symbol :
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之间的区别吗?我为之工作的人最初写的是这样的,没有构建错误

最佳答案

您应该使用nm -C来取消对符号的破坏。看起来您正在混合使用静态库和共享库,这通常不是一个好主意。同样,gcc的链接器是单程链接器,这意味着库标志的顺序很重要。您想以相反的依赖关系顺序列出库。换句话说,如果a依赖于b,则b必须在链接器标志中出现在a之前。

10-07 19:10