Cython:调用 C 函数抛出 'undefined symbol'
Cython: calling C function throws 'undefined symbol'
我正在尝试将 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.
的原型中都会发生
如果我导入另一个符号,比如说一个常量,我就可以访问它。所以我似乎在看正确的头文件。
我没有发现我的语法和文档之间有任何差异,但我显然做错了什么。有人可以给我提示吗?
谢谢。
要用 IPythons-magic 编译它(如果你能在你的问题中明确提到这一点会很好)你必须提供 library-path (通过 -L
-选项)和库名称(通过 -l
-选项)要包装的 built c-library,另请参阅 documentation:
%%cython -L=<path to your library> -l=<your_library>
您尝试打包的库不是 header-only 库。这意味着某些符号(例如 mdb_env_create
)仅在 header 中声明而未定义。构建库时,可以在生成的工件中找到这些符号的定义,构建扩展时应将其提供给链接器。这些定义是程序运行时所需要的。
如果您不这样做,Linux 会发生以下情况:构建扩展(*.so
文件)时,链接器默认允许未定义的符号 - 所以这一步是 "successful" - 但失败只是被推迟了。当通过 import
加载扩展时,Python 在 ldopen
的帮助下加载相应的 *.so
并且在此步骤中加载程序检查所有符号的定义是否已知。但是我们没有提供 mdb_env_create
的定义,所以加载器失败并显示
undefined symbol: mdb_env_create
在 header-file 中定义的符号不同,例如枚举 MDB_FIRST
&Co - 编译库不是必需的,因此可以加载扩展,因为没有未定义的符号。
我正在尝试将 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.
如果我导入另一个符号,比如说一个常量,我就可以访问它。所以我似乎在看正确的头文件。
我没有发现我的语法和文档之间有任何差异,但我显然做错了什么。有人可以给我提示吗?
谢谢。
要用 IPythons-magic 编译它(如果你能在你的问题中明确提到这一点会很好)你必须提供 library-path (通过 -L
-选项)和库名称(通过 -l
-选项)要包装的 built c-library,另请参阅 documentation:
%%cython -L=<path to your library> -l=<your_library>
您尝试打包的库不是 header-only 库。这意味着某些符号(例如 mdb_env_create
)仅在 header 中声明而未定义。构建库时,可以在生成的工件中找到这些符号的定义,构建扩展时应将其提供给链接器。这些定义是程序运行时所需要的。
如果您不这样做,Linux 会发生以下情况:构建扩展(*.so
文件)时,链接器默认允许未定义的符号 - 所以这一步是 "successful" - 但失败只是被推迟了。当通过 import
加载扩展时,Python 在 ldopen
的帮助下加载相应的 *.so
并且在此步骤中加载程序检查所有符号的定义是否已知。但是我们没有提供 mdb_env_create
的定义,所以加载器失败并显示
undefined symbol: mdb_env_create
在 header-file 中定义的符号不同,例如枚举 MDB_FIRST
&Co - 编译库不是必需的,因此可以加载扩展,因为没有未定义的符号。