简体   繁体   English

Python C Extensions - 为什么必须可调用的C函数接受参数并返回PyObject *

[英]Python C Extensions - Why must callable C functions take arguments and return PyObject *

I'm just starting to play with Python C extensions and am curious as to why a C function, which is callable from Python must take 2 PyObject* arguments and return a PyObject*. 我刚刚开始使用Python C扩展,并且很好奇为什么可以从Python调用的C函数必须使用2个PyObject *参数并返回PyObject *。 I wrote the following "Hello World" extension: 我写了以下“Hello World”扩展:

#include <Python.h>

static PyObject *
hello_world(PyObject *self, PyObject *noargs)
{
   printf("Hello World\n");
   return Py_BuildValue("");
}


// Module functions table.

static PyMethodDef
module_functions[] = {
    { "hello_world", hello_world, METH_NOARGS, "hello world method" },
    { NULL }
};


// This function is called to initialize the module.
PyMODINIT_FUNC
inittesty2(void)
{
    Py_InitModule("testy2", module_functions);
}

Why can't I (especially with METH_NOARGS) use the following hello_world method: 为什么我(特别是使用METH_NOARGS)不能使用以下hello_world方法:

static void
hello_world()
{
   printf("Hello World\n");
}

?

There are several things to say about the various PyObject pointers. 关于各种PyObject指针有几点要说。

  1. The one required as return type is used for the exception handling mechanism. 返回类型所需的一个用于异常处理机制。 Specifically, if your function returns a null pointer, the Python interpreter will throw an exception. 具体来说,如果您的函数返回空指针,Python解释器将抛出异常。 (You should only do that after calling one of the PyErr_.. functions to set a specific exception.) (您应该在调用其中一个PyErr_..函数后设置特定异常。)

    This also means that whenever you do not want to throw an exception, you must return a pointer to some real PyObject . 这也意味着无论何时不想抛出异常,都必须返回指向某个真实PyObject的指针。 If there is nothing in particular your function is supposed to return, simply return Py_None (best use the Py_RETURN_NONE macro to get the reference count right), or "true" (using Py_RETURN_TRUE ). 如果没有特别的函数应该返回,只需返回Py_None (最好使用Py_RETURN_NONE宏来使引用计数正确),或者返回“true”(使用Py_RETURN_TRUE )。

  2. The first argument , PyObject *self points to the object the function is called from, or to the module instance it belongs to. 一个参数 PyObject *self指向调用函数的对象,或指向它所属的模块实例。 Note that every function you define is either a class method, or a module method. 请注意, 您定义的每个函数都是类方法或模块方法。 There are no totally independent functions. 没有完全独立的功能。

  3. The second argument, PyObject *args points to the function argument (which may be a tuple or list of multiple arguments). 第二个参数PyObject *args指向函数参数(可以是元组或多个参数的列表)。 You are right in pointing out that a function that does not take any arguments should not need this — and, as far as I can tell, you are right. 你是正确的指出一个不带任何参数的函数不应该需要这个 - 而且,据我所知,你是对的。 You do not have to define it; 你不必定义它; you can simply define a function as 你可以简单地定义一个函数

     static PyObject *PyMyClass_MyFunc(PyObject *self) { /* ..do something.. */ Py_RETURN_TRUE; } 

    You will still have to cast this to PyCFunction when you put it into the PyMethodDef for the data type you define, but I believe that cast is safe as long as you use the METH_NOARGS flag. 当你把它放到你定义的数据类型的PyCFunction时,你仍然需要将它转换为PyMethodDef ,但我相信只要你使用METH_NOARGS标志, METH_NOARGS是安全的。 But note the comments below for possible risks. 但请注意以下评论可能存在的风险。

  4. Finally, a function may in fact have a third argument like this: 最后,函数实际上可能有第三个参数,如下所示:

     static PyObject *PyMyClass_Func(PyObject *self, PyObject *args, PyObject *kwds) { /*...*/ } 

    The third argument is used for named, optional arguments. 第三个参数用于命名的可选参数。 In this case, too, you must cast the function pointer to PyCFunction , but that, too, is safe if you set the right flag ( METH_KEYWORDS ) for your function in the method table. 在这种情况下,您也必须将函数指针PyCFunctionPyCFunction ,但如果您在方法表中为函数设置了正确的标志( METH_KEYWORDS ),那么这也是安全的。

The first argument for module level functions is the module object. 模块级函数的第一个参数是模块对象。 When defining classes in C (the same PyMethodDef structure is used for methods there), the first argument is the instance (similar to self in Python). 在C中定义类时(相同的PyMethodDef结构用于那里的方法),第一个参数是实例(类似于Python中的self )。

When using METH_NOARGS , Python will pass NULL as the second argument. 使用METH_NOARGS ,Python将传递NULL作为第二个参数。 They could cast it to a function with one argument but I guess they didn't think it's needed. 他们可以使用一个参数将其转换为函数,但我猜他们认为不需要它。

The return value is easy to explain. 返回值很容易解释。 Every Python function has a return value. 每个Python函数都有一个返回值。 If you don't explicitly use return in Python, the function will return None . 如果在Python中没有显式使用return ,则该函数将返回None

Of course in C you have to be explicit about the return value so if you don't use it, you have to return None yourself. 当然在C中你必须明确返回值,所以如果你不使用它,你必须自己返回None Python provides a macro for this: Python为此提供了一个宏:

Py_RETURN_NONE;

Alternatively you could access the global None instance yourself: 或者,您可以自己访问全局None实例:

Py_INCREF(Py_None);
return Py_None;

but the macro is easier to use. 但宏更容易使用。

You could think that returning NULL should be equivalent to None but NULL is used to indicate that the function raised an exception. 您可以认为返回NULL应该等于NoneNULL用于指示函数引发异常。

Because Python functions, even trivial ones that just print to stdout, are more than just wrappers around C functions. 因为Python函数,即使只是打印到stdout的微不足道的函数,也不仅仅是围绕C函数的包装器。

In the simplest case, think about the introspection facilities in Python. 在最简单的情况下,请考虑Python中的内省工具。 A Python function is a full-fledge object that you can query: Python函数是一个完整的对象,您可以查询:

>>> def hello():
...     print 'hello'
... 
>>> dir(hello)
['__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__doc__', '__format__', '__get__', '__getattribute__', '__globals__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name']

You could of course imagine an extension facility that just wrapped C functions. 你当然可以设想一个只包含C函数的扩展工具。 Check out SWIG , which lets your write extensions for lots of scripting languages, including Python. 查看SWIG ,它允许您编写许多脚本语言的扩展,包括Python。 Because it's going for the lowest common denominator, it'll let you wrap a function like your hello_world , but of course you lose a lot of power, too. 因为它是最低的共同点,所以它会让你包装像你的hello_world这样的函数,但当然你也失去了很多力量。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何从C的PyObject类型的函数返回从C到python的值? - How to return a value from C to python from C's PyObject type of functions? 在Python的C / C ++扩展中,返回的PyObject *应该具有哪些引用计数? - In C/C++ extensions to Python, what reference count should a returned PyObject* have? c++ 的 matplotlib 给出此错误:'PyObject_CallObject': function 不占用 3 ZDBC16FB4CAA5BDA882EBD77 - matplotlib for c++ gives this error: 'PyObject_CallObject': function does not take 3 arguments 创建带有附加函数的PyObject并返回到Python - Create a PyObject with attached functions and return to Python PyObject_GetAttrString C++ 函数返回 NULL:无法从 C++ 调用 Python 函数 - PyObject_GetAttrString C++ function returning NULL: Unable to call Python functions from C++ Python C API:打开PyObject类型 - Python C API: Switch on PyObject type 如何在Python中使用C ++处理PyObject * - how to deal with the PyObject* from C++ in Python 在 C++ 中的 PyObject 上调用 `+=` - Call `+=` on a PyObject in C++ SWIG返回PyObject作为python对象吗? - SWIG return PyObject as python object? 挑选一个Python扩展类型,定义为具有PyObject *成员的C结构 - Pickling a Python Extension type defined as a C struct having PyObject* members
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM