Python 3 - 用C扩展编程

使用任何编译语言(如C,C++或Java)编写的任何代码都可以集成或导入到另一个Python脚本中.此代码被视为"扩展名".

Python扩展模块只不过是一个普通的C库.在Unix机器上,这些库通常以 .so (对于共享对象)结束.在Windows机器上,您通常会看到 .dll (对于动态链接库).

编写扩展的先决条件

要开始编写扩展,您将需要Python头文件.

  • 在Unix机器上,这通常需要安装特定于开发人员的软件包

  • Windows用户在使用二进制Python安装程序时会将这些标头作为软件包的一部分.

此外,假设您对C或C&plus有很好的了解;并且;使用C编程编写任何Python扩展.

首先看一下Python扩展

首先看一下Python扩展模块,你需要将您的代码分为四部分和减号;

  • 头文件 Python.h .

  • 要作为模块接口公开的C函数.

  • 表映射函数的名称,因为Python开发人员将它们视为扩展模块中的C函数.

  • 初始化函数.

头文件Python.h

您需要在C中包含 Python.h 头文件源文件,它允许您访问用于将模块挂钩到解释器的内部Python API.

确保在您可能需要的任何其他标头之前包含Python.h.您需要使用包含要从Python调用的函数的包含.

C函数

函数的C实现的签名总是采用以下三种形式之一 :

static PyObject *MyFunction( PyObject *self, PyObject *args );

static PyObject *MyFunctionWithKeywords(PyObject *self, PyObject *args, PyObject *kw);

static PyObject *MyFunctionWithNoArgs( PyObject *self );

前面的每个声明都返回一个Python对象.在Python中没有像 void 那样的东西,如C中所有.如果你不希望你的函数返回一个值,则返回Python的C等价物值. Python标头定义了一个宏Py_RETURN_NONE,它为我们做了这个.

C函数的名称可以是你喜欢的任何东西,因为它们在扩展模块之外是从未见过的.它们被定义为 static 函数.

您的C函数通常通过将Python模块和函数名称组合在一起来命名,如下所示 :

static PyObject *module_func(PyObject *self, PyObject *args) {
   /* Do your stuff here. */
   Py_RETURN_NONE;
}

这是模块模块中名为 func 的Python函数.您将把指向C函数的指针放入源代码中通常出现的模块的方法表中.

方法映射表

此方法表是PyMethodDef结构的简单数组.该结构看起来像这样 :

struct PyMethodDef {
   char *ml_name;
   PyCFunction ml_meth;
   int ml_flags;
   char *ml_doc;
};

以下是此结构成员的描述 :

  • ml_name : 这是Python解释器在Python程序中使用时所呈现的函数名称.

  • ml_meth : 这是具有上一节中描述的任何一个签名的函数的地址.

  • ml_flags : 这告诉解释器ml_meth使用的三个签名中的哪一个.

    • 此标志的值通常为METH_VARARGS.

    • 如果你想在你的函数中允许关键字参数,可以用METH_KEYWORDS对这个标志进行按位OR运算.

    • 这也可以是METH_NOARGS的值,表示你不想接受任何参数.

  • ml_doc : 这是函数的docstring,如果你不想写一个函数,它可能是NULL.

这个表需要终止具有由适当成员的NULL和0值组成的标记.

示例

对于上面定义的函数,我们有以下方法映射表&减去;