如何将C方法附加到现有的Python类?
我们目前正在编写Python代码,其中使用了C方法。所有库(例如NumPy、OpenCV、PyTorch等)的基础都是用C和C++构建的,即这些库内部调用编译后的C代码,代码将在机器上执行,结果将返回到Python包装器中。
为什么我们在Python中使用C方法?
我们在Python中使用C方法的原因是性能。由于动态类型,Python的性能会下降。
在解释器执行操作之前,它必须减少要传递的操作数的类型。这些类型的操作会影响程序的执行时间。
C模块允许我们检查这些操作数并直接通过Python执行机器代码。
要使用C模块,我们必须将其与Python链接。将C模块与Python链接有多种方法。
一种方法是使用CPython API。要了解CPython API的工作原理和用法,使用此API的过程如下。
在Python中使用C API的过程
以下是使用Python中C API的步骤:
首先,我们必须安装python3-dev包才能在Python中使用C方法。可以使用以下代码安装该包。
pip install cpython
使用该代码后,我们必须创建一个名为extension的目录,并在该目录中创建一个扩展名为**extension.c**的文件。假设该文件名为**greet.c**,现在在这个文件中包含以下描述的头文件。
#include <python.h> #include <string.h>
CPython库将提供**python.h**头文件,还提供许多扩展函数和类型。这个库帮助我们集成Python和C。
示例
现在,让我们创建一个程序来使用CPython库。以下是可以用来使用CPython库的代码。
static PyObject* name(PyObject *self, PyObject* args){ char *name; char greeting[255] = "Hello "; if (!PyArg_ParseTuple(args, "s", &name)){ return NULL; } strcat(greeting, name); return Py_BuildValue("s", greeting); }
在上面的代码中,我们使用了PyObject。PyObject是在C中表示的Python实例。此PyObject函数有两个参数self和args。
self指示当前对象/模块
args用于指示Python参数。
定义我们的C方法
**PyArg_ParseTuple**传递到Python中,用于解释C值。第二个参数中的s是一个字符串值。如果是任何其他类型,它将在Python中抛出类型错误。**Py_BuildValue**与**PyArg_ParseTuple**相反。这意味着它从C解释Python中的值。
定义我们的C方法后,我们必须将其与Python接口。以下代码用于与Python进行解释。
static PyMethodDef moduleMethods[] = { {"name", name, METH_VARARGS, "Greets with your name"} };
现在,在将我们的C方法与Python接口之后,我们必须定义模块类型。以下代码可用于定义模块类型。
static struct PyModuleDef greetModule = { PyModuleDef_HEAD_INIT, "greet", "Greetings Module", -1, moduleMethods }; PyMODINIT_FUNC PyInit_greet(void){ return PyModule_Create(&greetModule); };
在当前程序中导入方法
现在,在定义方法类型并创建方法后,我们必须将其导入到我们的Python环境中。
import greet print("Name: ", greet.__name__) print("Docstring: ", greet.__doc__) print("Greeting: ", greet.name("Lezwon"))
如果我们执行上述代码,将会收到nomodulefound错误。这是因为该模块尚未与Python链接。因此,必须完成以下设置才能在Python中使用用C语言创建的模块。
setuptools
首先,我们必须在Python环境中安装setuptools。必须使用以下代码。
pip install setuptools
现在,我们必须使用Python扩展创建setup文件。以下代码将用于该Python文件中。
from setuptools import setup, Extension ext_modules = [ Extension('greet', sources = ['greetmodule.c']), ] setup( name = 'Greeting Project', ext_modules = ext_modules )
在上面的代码中,我们使用了greet。这表示我们在C中创建的模块。要编译我们的代码,我们必须使用以下命令。
python setup.py build_ext --inplace
现在我们可以运行以下代码。
import greet print("Name: ", greet.__name__) print("Docstring: ", greet.__doc__) print("Greeting: ", greet.name("Lezwon"))