如何将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 头文件,并为我们提供许多 many.py 扩展函数和类型。这个库帮助我们将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扩展名创建设置文件。下面的代码将在该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"))