Cython:调用C函数抛出未定义的符号'

时间:2018-06-07 00:20:25

标签: cython c-header

我试图在Cython中使用LMDB C API

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

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中输入的原型中都会发生这种情况。

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

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

感谢。

1 个答案:

答案 0 :(得分:1)

使用IPythons-magic编译它(如果你在你的问题中明确提到它会很好)你必须提供库路径(通过-L - 选项)和库名称(通过{{1}你要包装的构建的 c库的-option),另请参阅documentation

-l

您尝试换行的库不是仅限标头的库。这意味着某些符号(例如%%cython -L=<path to your library> -l=<your_library> )仅在标头中声明但未定义。构建库时,可以在生成的工件中找到这些符号的定义,这些工件应在构建扩展时提供给链接器。这些定义是程序运行时所需要的。

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

  

未定义的符号:mdb_env_create

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