Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python Function Capsules

I found this code snippet in the help of python 2.7.5, which is a chapter about exposing a C-API to other modules in the Extending Python with C and C++ section: Providing a C API for an Extension Module

/* C API functions */
#define PySpam_System_NUM 0
#define PySpam_System_RETURN int
#define PySpam_System_PROTO (const char *command)
// ...
static PySpam_System_RETURN PySpam_System PySpam_System_PROTO;
// ...
static void **PySpam_API;

#define PySpam_System \
(*(PySpam_System_RETURN (*)PySpam_System_PROTO) PySpam_API[PySpam_System_NUM])

This snipped is for function capsules. A capsule is used to pass functions between two modules. But what's the meaning of this snippet: [...] (PySpam_SystemRETURN (*)PySpam_System_PROTO) [...]. I think it's something like a static cast. Something like (int(*)(char s)). But what's the meaning of this construct?

like image 581
Sebi2020 Avatar asked Dec 15 '13 18:12

Sebi2020


People also ask

What are capsules in Python?

Refer to Providing a C API for an Extension Module for more information on using these objects. New in version 3.1. This subtype of PyObject represents an opaque value, useful for C extension modules who need to pass an opaque value (as a void* pointer) through Python code to other C code.

What is module object in Python?

A module is a Python object with arbitrarily named attributes that you can bind and reference. The Python code for a module named aname normally resides in a file named aname.py, as covered in Module Loading. In Python, modules are objects (values) and are handled like other objects.

How to compare capsule names in Python?

The name parameter must compare exactly to the name stored in the capsule. If the name stored in the capsule is NULL, the name passed in must also be NULL. Python uses the C function strcmp () to compare capsule names. Part of the Stable ABI. Return the current destructor stored in the capsule. On failure, set an exception and return NULL.

How to use funfunctions in Python?

Functions can be both built-in or user-defined. It helps the program to be concise, non-repetitive, and organized. We can create a Python function using the def keyword. After creating a function we can call it by using the name of the function followed by parenthesis containing parameters of that particular function.

What is the use of Def in Python?

It helps the program to be concise, non-repetitive, and organized. We can create a Python function using the def keyword. After creating a function we can call it by using the name of the function followed by parenthesis containing parameters of that particular function.

What is a function in Python?

A function is a block of code which only runs when it is called. You can pass data, known as parameters, into a function. A function can return data as a result. In Python a function is defined using the def keyword:


1 Answers

As defined, the macro PySpam_System expands into:

(*(int (*)(const char *command)) PySpam_API[0])

Which is basically accessing PySpam_API[0], casting it to a pointer to function receiving a const char * and returning int, and dereferencing that pointer.

It is equivalent to writing:

int (*)(const char *command) function_ptr = (int (*)(const char *command)) PySpam_API[0]
#define PySpam_System (*function_ptr)

That is, it is equivalent to declaring a variable function_ptr which is a pointer to the same function pointed to by PySpam_API[0] casted to int (*)(const char *), and then using PySpam_System as a shortcut to dereference the pointer, which means that PySpam_System can be used as if it were a function, as in:

PySpam_System("an example");

This effectively calls the function pointed to by PySpam_API[0] with argument "an example". Note that the function must be compatible with the cast.

Also, notice that the code defines a function called PySpam_System before defining the macro PySpam_System. This has the effect that if you use PySpam_System() before the #define, you will be calling this function:

static PySpam_System_RETURN PySpam_System PySpam_System_PROTO;

(Which expands to static int PySpam_System(const char *command);)

If you use PySpam_System() after the #define, you will be calling a macro that calls the function pointed to by PySpam_API[0].

like image 134
Filipe Gonçalves Avatar answered Oct 03 '22 08:10

Filipe Gonçalves