我试图在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中输入的原型中都会发生这种情况。
如果我导入另一个符号,说一个常量,我可以访问它。所以我似乎正在查看正确的头文件。
我没有看到我的语法和文档之间存在任何差异,但我显然做错了什么。有人可以给我一个暗示吗?
感谢。
答案 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 - 编译的库不是必需的,因此可以加载扩展名,因为没有未定义的符号。