使用Python3 C API添加到内置

时间:2017-11-01 12:16:19

标签: python python-3.x python-c-api

我希望使用Python3 C API添加内置函数。我这样做只是为了帮助我熟悉Python C API。 this问题的答案很好地解释了为什么人们可能不想这样做。无论如何,我想在Python foo模块中添加一个函数builtins

这是我迄今为止所做的事情(foo.c):

#include <Python.h>
#include <stdio.h>

static PyObject*
foo(PyObject *self, PyObject *args){
    printf("foo called");
    return Py_None;
}

char builtin_name[] = "builtins";
char foo_name[] = "foo";
char foo_doc[] = "foo function";

static PyMethodDef foo_method = {foo_name, foo, METH_NOARGS, foo_doc};

PyMODINIT_FUNC
PyInit_foo(void){
    PyObject *builtin_module = PyImport_ImportModule(builtin_name);
    PyModule_AddFunctions(builtin_module, &foo_method);
    return builtin_module;
}

我将它放在Python源目录的Modules/目录中。

1 个答案:

答案 0 :(得分:3)

仅仅因为你将它放在Modules/文件夹中并使用Python-C-API并不意味着它将被自动编译和执行。在将foo.c编译成Python扩展模块之后(确实如此,对吗?),您的代码(大致)等同于:

foo.py

def foo():
    """foo function"""
    print("foo called")

import builtins
builtins.foo = foo

Python实现中没有那么直接的事实是,当你import foo时,它不会返回foo模块而是builtins。但我想说这根本不是一个好主意,特别是因为你要添加的内置函数与你创建的模块具有相同的名称,所以很可能通过import foo覆盖了手动添加的{{1}再次......

除此之外:将它放在builtins.foo文件夹中并不意味着它在启动Python时实际导入。您需要自己使用Modules/或修改Python启动以导入它。

好的,除此之外,您应该问自己以下问题:

  • 你想编译自己的Python吗?如果是,那么您只需编辑import foo文件夹中的bltinsmodule.c,然后完全编译Python。
  • 你甚至想要编译任何东西,但不是完整的Python?如果是,那么就创建了自己的扩展模块(基本上就像你已经做过的那样),但是不要把它放在Python的Python/文件夹中,而是真正创建一个包(用Modules/完成等等)并且不要在module-init中返回setup.py模块。只需创建一个空模块,并在将builtins添加到foo模块后将其返回。并使用不同的模块名称,可能是builtins,因此它不会与新添加的_foo函数发生冲突。
  • 在这种情况下,Python-C-API和扩展模块是否正确?如果您认为Python-C-API会更容易添加到builtins.foo那么那就错了。 Python-C-API只允许更快的访问和对Python功能的更多访问。如果您只想做Python的东西(而不是C库的接口),那么使用普通Python模块无法用C-API做的事情很少。我会说,对于你的用例,创建一个扩展模块是完全矫枉过正的,所以也许只需使用普通的Python模块。

我的建议是使用上面提到的builtins并让Python在启动时导入它。为此,您将foo.py文件(我真的建议您将名称更改为类似foo.py的内容)放在安装其他软件包的目录(Windows上为_foo.py)并使用{{ 3}}(或另一种定制启动方法)在Python启动时导入该模块。