开发者社区> 问答> 正文

用Cython包装C代码

你想使用Cython来创建一个Python扩展模块,用来包装某个已存在的C函数库。

展开
收起
哦哦喔 2020-04-17 18:13:51 2238 0
2 条回答
写回答
取消 提交回答
  • 有点尴尬唉 你要寻找的东西已经被吃掉啦!

    用Cython包装C代码:可以参考这篇文章: https://www.baidu.com/link?url=6djl4oF9q-bjXsKIc7n5xA5eoO3YbD_ISURCaytWx9o0B2dmmEhXclgxb_R

    2020-04-17 23:57:26
    赞同 展开评论 打赏
  • 使用Cython构建一个扩展模块看上去很手写扩展有些类似, 因为你需要创建很多包装函数。不过,跟前面不同的是,你不需要在C语言中做这些——代码看上去更像是Python。
    
    作为准备,假设本章介绍部分的示例代码已经被编译到某个叫 libsample 的C函数库中了。 首先创建一个名叫 csample.pxd 的文件,如下所示:
    
    # csample.pxd
    #
    # Declarations of "external" C functions and structures
    
    cdef extern from "sample.h":
        int gcd(int, int)
        bint in_mandel(double, double, int)
        int divide(int, int, int *)
        double avg(double *, int) nogil
    
        ctypedef struct Point:
             double x
             double y
    
        double distance(Point *, Point *)
    这个文件在Cython中的作用就跟C的头文件一样。 初始声明 cdef  extern  from  "sample.h" 指定了所学的C头文件。 接下来的声明都是来自于那个头文件。文件名是 csample.pxd ,而不是 sample.pxd ——这点很重要。
    
    下一步,创建一个名为 sample.pyx 的问题。 该文件会定义包装器,用来桥接Python解释器到 csample.pxd 中声明的C代码。
    
    # sample.pyx
    
    # Import the low-level C declarations
    cimport csample
    
    # Import some functionality from Python and the C stdlib
    from cpython.pycapsule cimport *
    
    from libc.stdlib cimport malloc, free
    
    # Wrappers
    def gcd(unsigned int x, unsigned int y):
        return csample.gcd(x, y)
    
    def in_mandel(x, y, unsigned int n):
        return csample.in_mandel(x, y, n)
    
    def divide(x, y):
        cdef int rem
        quot = csample.divide(x, y, &rem)
        return quot, rem
    
    def avg(double[:] a):
        cdef:
            int sz
            double result
    
        sz = a.size
        with nogil:
            result = csample.avg(<double *> &a[0], sz)
        return result
    
    # Destructor for cleaning up Point objects
    cdef del_Point(object obj):
        pt = <csample.Point *> PyCapsule_GetPointer(obj,"Point")
        free(<void *> pt)
    
    # Create a Point object and return as a capsule
    def Point(double x,double y):
        cdef csample.Point *p
        p = <csample.Point *> malloc(sizeof(csample.Point))
        if p == NULL:
            raise MemoryError("No memory to make a Point")
        p.x = x
        p.y = y
        return PyCapsule_New(<void *>p,"Point",<PyCapsule_Destructor>del_Point)
    
    def distance(p1, p2):
        pt1 = <csample.Point *> PyCapsule_GetPointer(p1,"Point")
        pt2 = <csample.Point *> PyCapsule_GetPointer(p2,"Point")
        return csample.distance(pt1,pt2)
    该文件更多的细节部分会在讨论部分详细展开。 最后,为了构建扩展模块,像下面这样创建一个 setup.py 文件:
    
    from distutils.core import setup
    from distutils.extension import Extension
    from Cython.Distutils import build_ext
    
    ext_modules = [
        Extension('sample',
    
                  ['sample.pyx'],
                  libraries=['sample'],
                  library_dirs=['.'])]
    setup(
      name = 'Sample extension module',
      cmdclass = {'build_ext': build_ext},
      ext_modules = ext_modules
    )
    要构建我们测试的目标模块,像下面这样做:
    
    bash % python3 setup.py build_ext --inplace
    running build_ext
    cythoning sample.pyx to sample.c
    building 'sample' extension
    gcc -fno-strict-aliasing -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes
     -I/usr/local/include/python3.3m -c sample.c
     -o build/temp.macosx-10.6-x86_64-3.3/sample.o
    gcc -bundle -undefined dynamic_lookup build/temp.macosx-10.6-x86_64-3.3/sample.o
      -L. -lsample -o sample.so
    bash %
    如果一切顺利的话,你应该有了一个扩展模块 sample.so ,可在下面例子中使用:
    
    >>> import sample
    >>> sample.gcd(42,10)
    2
    >>> sample.in_mandel(1,1,400)
    False
    >>> sample.in_mandel(0,0,400)
    True
    >>> sample.divide(42,10)
    (4, 2)
    >>> import array
    >>> a = array.array('d',[1,2,3])
    >>> sample.avg(a)
    2.0
    >>> p1 = sample.Point(2,3)
    >>> p2 = sample.Point(4,5)
    >>> p1
    <capsule object "Point" at 0x1005d1e70>
    >>> p2
    <capsule object "Point" at 0x1005d1ea0>
    >>> sample.distance(p1,p2)
    2.8284271247461903
    >>>
    
    2020-04-17 18:14:00
    赞同 展开评论 打赏
问答分类:
问答地址:
问答排行榜
最热
最新

相关电子书

更多
Python系列直播第一讲——Python中的一切皆对象 立即下载
低代码开发师(初级)实战教程 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载