0

我正在尝试将LMDB C API与 Cython 一起使用。

我想从头文件中导入以下定义:

typedef struct MDB_env MDB_env;
int  mdb_env_create(MDB_env **env);

所以我创建了一个.pxd文件:

cdef extern from 'lmdb.h':
    struct MDB_env:
        pass
    int  mdb_env_create(MDB_env **env)

我在 Cython 脚本中使用它:

cdef MDB_env *e
x = mdb_env_create(&e)

这段代码编译得很好,但如果我运行它,我会得到:

ImportError: /home/me/.cache/ipython/cython/_cython_magic_15705c11c6f56670efe6282cbabe4abc.cpython-36m-x86_64-linux-gnu.so: undefined symbol: mdb_env_create

这既发生在 Cython .pyx+.pxd设置中,也发生在 IPython 中键入的原型中。

如果我导入另一个符号,比如一个常量,我可以访问它。所以我似乎正在查看正确的头文件。

我没有看到我的语法和文档之间有任何差异,但我显然做错了什么。有人可以给我一个提示吗?

谢谢。

4

1 回答 1

2

要使用 IPythons-magic 编译它(如果您在问题中明确提及这一点会很好),您必须提供您想要的已构建-Lc 库的库路径(通过-option)和库名称(通过-l-option)换行,另请参阅文档

%%cython  -L=<path to your library> -l=<your_library>

您尝试包装的库不是仅标头库。这意味着某些符号(例如mdb_env_create)仅在标头中声明但未定义。构建库时,可以在生成的工件中找到这些符号的定义,构建扩展时应将其提供给链接器。这些定义是程序运行时所需要的。

如果你不这样做,在 Linux 上会发生以下情况: 当扩展(*.so-file)被构建时,链接器默认允许未定义的符号——所以这一步是“成功的”——但失败只是被推迟了。当通过 加载扩展时,Python 会在的帮助下import加载相应的,并且在此步骤中,加载器会检查所有符号的定义是否已知。但是我们没有提供这样的定义,加载器失败了*.soldopenmdb_env_create

未定义符号:mdb_env_create

对于在头文件中定义的符号,例如 enums MDB_FIRST&Co 是不同的 - 编译库不是必需的,因此可以加载扩展,因为没有未定义的符号。

于 2018-06-07T06:40:53.260 回答