使用 Cython 公开静态链接的 c 库符号
Use Cython for exposing statically linked c-library symbols
我有一个关于如何将本地 C 库中的代码与 Cython 一起使用的最佳实践的问题。为了避免设置 LD_LIBRARY_PATH
(或在 /usr/lib 或类似目录中安装 C 库),我认为静态链接是适合我的用例的解决方案。
但是,连接已静态链接的 c 函数并非易事。我可以 cimport
另一个具有静态链接 C 代码的 cython 模块的唯一方法是用 Cython 函数指针解释所有导出的函数(参见 https://github.com/HolgerPeters/cython-example/blob/master/cython-project/c_with_ptrs.pyx and https://github.com/HolgerPeters/cython-example/blob/master/cython-project/c_with_ptrs.pxd)
仅仅将 pxd 中的原始 C 函数声明为 extern 似乎不起作用。我在 Github 上有一个示范项目,它隔离了不同的方法及其用法。
https://github.com/HolgerPeters/cython-example
对此有什么想法吗?我可以告诉 Cython 显式使用 extern
ed 声明吗?
特定的堆栈跟踪
由于这个问题一开始是一个相当开放的问题,我想让它更具体以鼓励回答。
在名为 github 的项目中,我组合了几种链接方式。我现在将重点放在文档中看起来很自然的方式上。
来自 "foo.h" 的 cdef 外部:
外部整数 clib_return_3(整数)
定义使用它():
打印(clib_return_3(4))
调用 c_from_with_direct_compilation.useit() 有效(test.sh 输出如下)。
但是当我尝试使用另一个 cython 文件中的 clib_return_3
时,它失败了!用法是
导入 c_from
定义使用它():
打印(c_from.clib_return_3(4))
bash test.sh
测试所有使用情况,如您所见,cython 所以 clib_return_3 符号链接到的地方确实可以使用该符号,而另一个 cython 则试图导入它符号在此失败。
======================== c_from_w/_direct_comp,接口失败(为什么?)
从静态链接 c_from_with_direct_compilation 调用,通过 c_from_with_direct_compilation_user 调用
追溯(最近一次通话):
文件“”,第 1 行,位于
导入错误:./c_from_with_direct_compilation_user.so:未定义的符号:clib_return_3
失败
========================c_from_w/_direct_comp
从静态链接调用 c_from_with_direct_compilation
3个
成功
您可以执行以下任一操作:
cdef extern from "path/header.h":
然后列出您将在 cython 中使用的函数定义。 (http://docs.cython.org/src/userguide/external_C_code.html#referencing-c-header-files)
- 将 C 函数声明为
extern
。 (http://docs.cython.org/src/userguide/external_C_code.html#external-declarations)
(这两种方法都适用于 pyx
和 pxd
文件)。
旁注:在您的 setup.py
中,您使用了 2 种不同的方式来包含 C 代码(使用动态库和使用目标文件)。除非你的 C make 规则真的很复杂,否则第三种选择是将 .c
文件列在与 .pyx
文件相同的数组中,让 distutils 为你构建它们。
在盯着这个问题看够久之后,我想我知道发生了什么事了:
Cython-cdef-functions 的名称经过了修饰,而 extern 函数没有经过名称修饰并保留了它们的原始名称。名称修饰对于跨不同模块的功能的可发现性是必要的。因此,无法通过 cimport
共享未损坏的名称 - 对于那些,适用普通的 C 共享库机制。
我有一个关于如何将本地 C 库中的代码与 Cython 一起使用的最佳实践的问题。为了避免设置 LD_LIBRARY_PATH
(或在 /usr/lib 或类似目录中安装 C 库),我认为静态链接是适合我的用例的解决方案。
但是,连接已静态链接的 c 函数并非易事。我可以 cimport
另一个具有静态链接 C 代码的 cython 模块的唯一方法是用 Cython 函数指针解释所有导出的函数(参见 https://github.com/HolgerPeters/cython-example/blob/master/cython-project/c_with_ptrs.pyx and https://github.com/HolgerPeters/cython-example/blob/master/cython-project/c_with_ptrs.pxd)
仅仅将 pxd 中的原始 C 函数声明为 extern 似乎不起作用。我在 Github 上有一个示范项目,它隔离了不同的方法及其用法。
https://github.com/HolgerPeters/cython-example
对此有什么想法吗?我可以告诉 Cython 显式使用 extern
ed 声明吗?
特定的堆栈跟踪
由于这个问题一开始是一个相当开放的问题,我想让它更具体以鼓励回答。
在名为 github 的项目中,我组合了几种链接方式。我现在将重点放在文档中看起来很自然的方式上。
来自 "foo.h" 的 cdef 外部: 外部整数 clib_return_3(整数)
定义使用它(): 打印(clib_return_3(4))
调用 c_from_with_direct_compilation.useit() 有效(test.sh 输出如下)。
但是当我尝试使用另一个 cython 文件中的 clib_return_3
时,它失败了!用法是
导入 c_from 定义使用它(): 打印(c_from.clib_return_3(4))
bash test.sh
测试所有使用情况,如您所见,cython 所以 clib_return_3 符号链接到的地方确实可以使用该符号,而另一个 cython 则试图导入它符号在此失败。
======================== c_from_w/_direct_comp,接口失败(为什么?) 从静态链接 c_from_with_direct_compilation 调用,通过 c_from_with_direct_compilation_user 调用 追溯(最近一次通话): 文件“”,第 1 行,位于 导入错误:./c_from_with_direct_compilation_user.so:未定义的符号:clib_return_3 失败 ========================c_from_w/_direct_comp 从静态链接调用 c_from_with_direct_compilation 3个 成功
您可以执行以下任一操作:
cdef extern from "path/header.h":
然后列出您将在 cython 中使用的函数定义。 (http://docs.cython.org/src/userguide/external_C_code.html#referencing-c-header-files)- 将 C 函数声明为
extern
。 (http://docs.cython.org/src/userguide/external_C_code.html#external-declarations)
(这两种方法都适用于 pyx
和 pxd
文件)。
旁注:在您的 setup.py
中,您使用了 2 种不同的方式来包含 C 代码(使用动态库和使用目标文件)。除非你的 C make 规则真的很复杂,否则第三种选择是将 .c
文件列在与 .pyx
文件相同的数组中,让 distutils 为你构建它们。
在盯着这个问题看够久之后,我想我知道发生了什么事了:
Cython-cdef-functions 的名称经过了修饰,而 extern 函数没有经过名称修饰并保留了它们的原始名称。名称修饰对于跨不同模块的功能的可发现性是必要的。因此,无法通过 cimport
共享未损坏的名称 - 对于那些,适用普通的 C 共享库机制。