使用 cffi 加载 .so 库

loading .so library with cffi

我想使用 CFFI 在 Python 中访问一些 C 库。构建库后,我得到了 2 个文件:$HOME/libcint/include/cint.h$HOME/libcint/lib/libcint.so.

现在我尝试了 CFFI API 模式:

from cffi import FFI
libcint_dir = os.path.expanduser('~/libcint')
ffibuilder = FFI()
ffibuilder.set_source('_libcint',
  r'#include <include/cint.h>',
  include_dirs = [libcint_dir],
  libraries = ['libcint'],
  library_dirs = [os.path.join(libcint_dir, 'lib')],
)

但是找不到 libcint.so 文件:

/usr/bin/ld: cannot find -llibcint

libcint_dir中的路径是正确的,因为我没有收到任何关于找不到头文件的错误信息。我还设法使用 ctypes 模块成功连接了库,因此 libcint.so 本身应该没问题。

我做错了什么?

如果我做对了,那么这里需要 3 个步骤。 (如果我在这里混淆了什么,请纠正我。)

  1. 编译 libcint 产生 libcint.so
  2. 使用 CFFI
  3. 构建 Python 包装器
  4. 将步骤 2 中构建的模块导入到实际的 Python 程序中

我这里的问题是关于第二步的。

您可能被编译时间与库的 运行 时间位置的问题困扰。您提供给库的路径仅在 GCC 编译时使用。在 运行 时,它会查找名称正确的库,但仅使用系统配置的默认路径。所以你需要告诉系统在哪里可以找到那个库。您可以执行以下操作之一:

  • 将库移动到标准位置,如 /usr/local/lib;

  • 运行 加上环境变量 LD_LIBRARY_PATH=/path/to/library;

  • 如果你想在编译模块中硬编码路径,你可以在调用set_source()时使用extra_link_args=['-Wl,-rpath=' + path]

这都是假设 Linux。在不同的平台上,这三个选项可能也都可用,但细节有所不同...

您说的是 libraries = ['libcint'],这意味着编译器将查找名为 liblibcint.so 的文件。因此你应该写的是 libraries = ['cint'].