[英]Use Cython for exposing statically linked c-library symbols
I have a question on best practice on how to use code from a local C library with Cython. 我对如何在Cython中使用本地C库中的代码的最佳实践有一个疑问。 In order to avoid setting the
LD_LIBRARY_PATH
(or installing the C library in /usr/lib or similar directories), I think static linking would be a suitable solution for my use case. 为了避免设置
LD_LIBRARY_PATH
(或在/ usr / lib或类似目录中安装C库),我认为静态链接将是适合我的用例的解决方案。
However, interfacing the c functions that have been statically linked is non-trivial. 但是,连接已经静态链接的c函数并非易事。 The only way I could
cimport
another cython module that has statically linked C code in it was to paraphrase all exported functions with Cython function pointers (see 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 ) 我可以
cimport
另一个具有静态链接的C代码的cython模块的唯一方法是使用Cython函数指针对所有导出的函数进行释义(请参阅https://github.com/HolgerPeters/cython-example/blob/master/cython-project /c_with_ptrs.pyx和https://github.com/HolgerPeters/cython-example/blob/master/cython-project/c_with_ptrs.pxd )
Just declaring the original C function in the pxd as extern does not seem to work. 仅将pxd中的原始C函数声明为extern似乎不起作用。 I have exemplary project on Github which isolates different approaches and their usage.
我在Github上有一个示范项目,它隔离了不同的方法及其用法。
https://github.com/HolgerPeters/cython-example https://github.com/HolgerPeters/cython-example
Any ideas on this? 有什么想法吗? Can I tell Cython to explicitly use the
extern
ed declarations? 我可以告诉Cython显式使用
extern
ed声明吗?
As the question started as a rather open one, I would like to make it more specific to encourage answers. 由于这个问题是一个比较开放的问题,因此我想更具体地鼓励人们回答。
In the named github project I have assembled several ways of linking. 在命名的github项目中,我组装了几种链接方式。 I will focus now on the way that seems natural from the documentation.
我现在将集中于文档中看起来很自然的方式。
https://github.com/HolgerPeters/cython-example/blob/master/cython-project/c_from_with_direct_compilation.pxd https://github.com/HolgerPeters/cython-example/blob/master/cython-project/c_from_with_direct_compilation.pxd
cdef extern from "foo.h": extern int clib_return_3(int)
and a use case in the corresponding https://github.com/HolgerPeters/cython-example/blob/master/cython-project/c_from_with_direct_compilation.pyx 以及相应https://github.com/HolgerPeters/cython-example/blob/master/cython-project/c_from_with_direct_compilation.pyx中的用例
def useit(): print(clib_return_3(4))
Invocation of c_from_with_direct_compilation.useit() works (test.sh output below). 调用c_from_with_direct_compilation.useit()起作用(下面的test.sh输出)。
But then when I try to use clib_return_3
from another cython file, it fails! 但是,当我尝试从另一个cython文件中使用
clib_return_3
,它将失败! Usage is 用法是
https://github.com/HolgerPeters/cython-example/blob/master/cython-project/c_from_with_direct_compilation_user.pyx https://github.com/HolgerPeters/cython-example/blob/master/cython-project/c_from_with_direct_compilation_user.pyx
cimport c_from def useit(): print(c_from.clib_return_3(4))
bash test.sh
tests all usage cases, and as you can see, the cython so where the clib_return_3 symbol is linked into can indeed use that symbol, whereas the other cython so trying to import that symbol fails at this. bash test.sh
测试所有使用情况,并且您可以看到cython,因此将clib_return_3符号链接到的地方确实可以使用该符号,而尝试导入该符号的另一个cython在此失败。
======================== c_from_w/_direct_comp, interfacing fails (why?) Invoke from statically linked c_from_with_direct_compilation, invocation by c_from_with_direct_compilation_user Traceback (most recent call last): File "", line 1, in ImportError: ./c_from_with_direct_compilation_user.so: undefined symbol: clib_return_3 FAILURE ======================== c_from_w/_direct_comp Invoke from statically linked c_from_with_direct_compilation 3 SUCCESS
You can do either of: 您可以执行以下任一操作:
cdef extern from "path/header.h":
and then list the function defs you'll use in cython. cdef extern from "path/header.h":
然后列出要在cython中使用的函数defs。 ( http://docs.cython.org/src/userguide/external_C_code.html#referencing-c-header-files ) extern
. extern
。 ( http://docs.cython.org/src/userguide/external_C_code.html#external-declarations ) (Both methods work in pyx
and pxd
files). (这两种方法都可以在
pyx
和pxd
文件中使用)。
Side note: in your setup.py
, you're using 2 different ways to include the C code (using the dynamic library & using the object file). 旁注:在
setup.py
,您使用2种不同的方式包含C代码(使用动态库和使用目标文件)。 Unless your C make rules are really complicated, a third option is to just list the .c
files in the same array as the .pyx
files and let distutils build them for you. 除非您的C make规则真的很复杂,否则第三个选择是仅将
.c
文件与.pyx
文件放在同一数组中,然后让distutils为您构建它们。
After staring long enough at this problem I think I know what is going on: 在凝视了这个问题足够长时间之后,我想我知道发生了什么事:
Cython-cdef-functions are name mangled, whereas extern functions are not name-mangled and keep their original names. Cython-cdef函数名称混乱,而extern函数没有名称混杂,并保留其原始名称。 Name mangling is necessary for discoverability of functions across different modules.
为了在不同模块之间发现功能,必须进行名称修饰。 So non-mangled names cannot be shared via
cimport
- for those, the normal C shared library mechanisms apply. 因此,无法通过
cimport
共享非混合名称-对于这些名称,将应用常规C共享库机制。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.