如何将 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 的目录,并在该目录中创建一个扩展名为 .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 扩展创建 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"))