标签: Cython

  • 用Cython把Python模块转换为纯C语言模块

    转换为C语言模块后可以与Python解释器编译到一起作为内置模块用,也可以外部模块import后使用。

    1. 创建嵌入式模块

    嵌入式模块可以嵌入到独立C语言程序中执行
    首先编写普通的python模块代码,然后在python代码的基础上创建pyx代码,通过cdef声明可以定义原生C语言函数,而不用通过Python解释器调用,可以更好的与C语言交互。
    pyx代码的写法可以参考cython官方文档
    hello.pyx文件

    cdef public char *say_hello_to(char* name):
        return name
    

    c-test.c文件

    #include "Python.h"
    #include "hello.h"
    int main(int argc, char *argv[])
    {
        PyObject *pmodule;
        char *result;
        wchar_t *program;
    
       // 读取命令行参数
        program = Py_DecodeLocale(argv[0], NULL);
        if (program == NULL) {
            fprintf(stderr, "Fatal error: cannot decode argv[0], got %d arguments\n", argc);
            exit(1);
        }
        /* 把模块注册为内置模块 */
    
        if (PyImport_AppendInittab("test", PyInit_hello) == -1) {
    
            fprintf(stderr, "Error: could not extend in-built modules table\n");
    
            exit(1);
    
        }
        /* 把命令行参数传给Python解释器 */
        Py_SetProgramName(program);
    
        /* 初始化Python,这一步是必须的. */
        Py_Initialize();
    
        /* 调用Python中的函数. */
        result = say_hello_to("hetao");
        // PyErr_Print();
        printf("result:%s\n", result);
    
          /* Clean up after using CPython. */
        PyMem_RawFree(program);
        Py_FinalizeEx();
    
        return 0;
    
        /* Clean up in the error cases above. */
    exit_with_error:
        PyMem_RawFree(program);
        Py_Finalize();
        return 1;
    }
    

    cython hello.pyx --3str
    执行cython后会生成hello.c和hello.h两个文件

    gcc -o libhello.so -shared  -fPIC -I/usr/include/python3.10 hello.c
    gcc -o test-c -I/usr/include/python3.10 -I./ -L./ -ltest -lpython3.10 -Wl,-rpath . test-c.c
    

    运行结果

    $ ./test-c
    result:hetao

    2. 创建外部模块

    hello.pyx文件

    def say_hello_to(name):
        return name
    

    setup.py文件

    from setuptools import setup
    from Cython.Build import cythonize
    
    setup(
        name='Hello',
        ext_modules=cythonize("hello.pyx"),
    )
    

    构建模块
    python setup.py build_ext --inplace

    test-hello.py文件

    import hello
    
    result = hello.say_hello_to("hetao")
    print(result)
    

    cdef、def 和 cpdef 的区别:

    在 Cython 中,有三种不同的函数声明方式:cdef、def 和 cpdef。
    cdef 声明的函数是纯 C 函数,只能从 Cython 代码中调用,不可从 Python 代码中访问。
    def 声明的函数是 Python 函数,可以从 Python 代码中调用,但会带来一些性能开销。
    cpdef 声明的函数是混合函数,既可以从 Cython 代码中调用,也可以从 Python 代码中调用,其底层其实生成了两个函数版本。

    关于编译参数:

    获取编译参数
    python3-config –cflags
    获取链接参数
    python3-config –ldflags

    Views: 1