转换为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