环境要求:C/C++编译器,gcc或者MSVC均可
参考自官方文档
使用python-api编写c语言代码
首先写一个简单的参数传递函数args_show()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| #include <Python.h> #include <stdio.h>
static PyObject* args_show(PyObject *self, PyObject *args, PyObject *kwargs){ char* a; char* b; char *foo = "default foo"; char *bar = "default bar"; char *baz = "default baz"; static char* kwlist[] = {"a", "b", "foo", "bar", "baz", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss|sss", kwlist, &a, &b, &foo, &bar, &baz)) { Py_RETURN_NONE; }
printf("a is %s\n", a); printf("b is %s\n", b); printf("foo is %s\n", foo); printf("bar is %s\n", bar); printf("baz is %s\n", baz);
Py_RETURN_NONE; }
|
使用Python-api对函数进行封装以及注册
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
|
static PyMethodDef KeywodsMethod[] = { {"args_show", (PyCFunction)(void(*)(void))args_show, METH_VARARGS|METH_KEYWORDS, "pratice kwargs"}, {NULL, NULL, 0, NULL} };
static struct PyModuleDef testmodule = { PyModuleDef_HEAD_INIT, "test", "some docs", -1, KeywodsMethod, };
PyMODINIT_FUNC PyInit_test(void){ PyObject *m;
m = PyModule_Create(&testmodule); if (m == NULL) return NULL;
return m; }
|
使用setup.py
对模块进行编译
from setuptools import Extension, setup
module = Extension( "test", sources=["./test.c"] )
setup( ext_modules=[module] )
|
之后使用python setup.py build_ext --inplace
对源文件进行编译。编译后会在当前目录看到一个test.cpxx-xxx_xxx.pyd
文件(xxx为编译平台信息)。因为使用了--inplace
,如果模块名为xxx.test
,编译后的文件会在xxx模块目录下生成。
测试
相同目录下新建一个测试文件导入方法进行测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| from test import args_show args_show("1", "2")
args_show("1", "2", "foo", "bar")
|
由于自己编写的C拓展模块没有对应的类型注解,可以自己在pyd
同目录下编写一个同名的pyi
文件用于类型注解
def args_show(a: str, b: str, foo: str = "default foo", bar: str = "default bar", baz: str = "default baz") -> None : ...
|