-
说明
尝试翻译Cython Documentation以助学习。
水平有限,乐迎指正;文档首页:《Cython官方文档中文翻译》
-
调用C函数
此教程简述了从
Cython
代码中调用C库函数的必要知识,关于使用额外C库、封装、处理错误的更深入理解,参见Using C libraries。简单起见,从C标准库中的一个函数开始。这不会向代码添加任何依赖性,还有个额外优势,就是
Cython
已经为你定义了很多类似函数。因此你只需cimport并使用。例如,假设你需要一种低级的方式来对
char*
值解析出数。你可以用stdlib.h
头文件定义的*atoi()*函数,操作如下:from libc.stdlib cimport atoi cdef parse_charptr_to_py_int(char* s): assert s is not NULL, "byte string value is NULL" return atoi(s) # atoi()函数没有错误检查机制
你可以在
Cython
的源文件Cython/Includes/中找到这些标准cimport文件的完整列表。他们存储在*.pyx文件中,提供可跨模块共享可复用的Cython声明*的标准方式。(详情参见 Sharing Declarations Between Cython Modules)Cython
也有完整一套用于CPython的C-API的声明,例如,为测试在C编译
时你的代码正用CPython的哪个版本编译,你可以:from cpython.version cimport PY_VERSION_HEX print(PY_VERSION_HEX >= 0x030200F0)
Cython
还提供对C数学库的声明:from libc.math cimport sin cdef double f(double x): return sin(x * x)
-
动态链接
libc数学库的独特在于,在某些
类Unix系统
上,未链接它,比如Linux
。为cimport这些声明,你必须配置构建系统以链接共享库m
。对于distutils
,只需将其添加到Extension()设置的libraries参数:from distutils.core import setup from distutils.extension import Extension from Cython.Build import cythonize ext_modules = [ Extension("demo", source = ["demo.pys"], libraries = ["m"]) # 类Unix特有 ] setup(name="Demos",ext_modules = cythonize(ext_modules))
-
其他声明
如果你想访问
Cython
没有直接备好声明的C代码
,你必须自己声明它。例如,前面提到的*sin()*函数定义方式如下:cdef extern from "math.h": double sin(double x)
上述代码声明了sin()函数,使之可用于Cython代码,并指示
Cython
在生成C代码时包含math.h头文件。C编译器在编译过程中会识别math.h文件中的原始声明,然而Cython
并不会解析*“math.h”*因此需要一个单独的声明。就像math库中的sin()函数,只要
Cython
生成的模块正确链接共享库或静态库,就可以声明或调用任何C库。你可以通过声明cpdef,从Cython模块中输出任何C函数。这将为它生成一个Python包装器,并添加到module dict中。下面是一个Cython模块,它实现了
Python
代码直接访问C
*sin()*函数:""" >>> sin(0) 0.0 """ cdef extern from "math.h": cpdef double sin(double x)
如果上述声明出现在属于Cython模块(详情参见 Sharing Declarations Between Cython Modules)的*.pyd*文件中效果是一样的。
这允许Cython模块复用C声明,同时在这个特殊模块中自动生成Python包装器。
-
命名参数
C
和Cython
都支持像这样没有参数的签名声明:cdef extern from "string.h": char* strstr(const char*, const char*)
但是,这可以防止
Cython
代码使用关键字参数调用它。因此下面写法更优:cdef extern from "string.h": char* strstr(const char *haystack, const char *needle)
这样就很清楚在调用中这两个参数各自做了什么,避免歧义同时增加代码可读性:
cdef extern from "string.h": char* strstr(const char *haystack, const char *needle) cdef char* data = "hfvcakdfagbcffvschvxcdfgccbcfhvgcsnfxjh" cdef char* pos = strstr(needle= "akd", haystack= data) print(pos is not NULL)
后续更变已存在参数是一种后向不兼容API修改,就如Python代码。因此,如果你自定义
C
或C++
函数声明,通常值得花费额外的精力来选择他们的参数名。 -
References
Cython官方文档中文翻译:调用C函数
猜你喜欢
转载自blog.csdn.net/The_Time_Runner/article/details/103672347
今日推荐
周排行