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?
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.
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.
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.
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.
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.
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:
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]
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With