2018-06-19 17:55:39 -04:00
|
|
|
|
PEP: 580
|
|
|
|
|
Title: The C call protocol
|
|
|
|
|
Author: Jeroen Demeyer <J.Demeyer@UGent.be>
|
2019-03-24 07:11:27 -04:00
|
|
|
|
BDFL-Delegate: Petr Viktorin
|
2019-05-07 09:54:15 -04:00
|
|
|
|
Status: Rejected
|
2018-06-19 17:55:39 -04:00
|
|
|
|
Type: Standards Track
|
|
|
|
|
Content-Type: text/x-rst
|
|
|
|
|
Created: 14-Jun-2018
|
|
|
|
|
Python-Version: 3.8
|
2018-07-16 12:36:35 -04:00
|
|
|
|
Post-History: 20-Jun-2018, 22-Jun-2018, 16-Jul-2018
|
2018-06-19 17:55:39 -04:00
|
|
|
|
|
|
|
|
|
|
2019-05-07 09:54:15 -04:00
|
|
|
|
Rejection Notice
|
|
|
|
|
================
|
|
|
|
|
|
2022-01-21 06:03:51 -05:00
|
|
|
|
This PEP is rejected in favor of :pep:`590`, which proposes a simpler public
|
2019-05-07 09:54:15 -04:00
|
|
|
|
C API for callable objects.
|
|
|
|
|
|
|
|
|
|
|
2018-06-19 17:55:39 -04:00
|
|
|
|
Abstract
|
|
|
|
|
========
|
|
|
|
|
|
|
|
|
|
A new "C call" protocol is proposed.
|
|
|
|
|
It is meant for classes representing functions or methods
|
|
|
|
|
which need to implement fast calling.
|
2018-09-21 17:31:11 -04:00
|
|
|
|
The goal is to generalize all existing optimizations for built-in functions
|
2018-06-19 17:55:39 -04:00
|
|
|
|
to arbitrary extension types.
|
|
|
|
|
|
|
|
|
|
In the reference implementation,
|
|
|
|
|
this new protocol is used for the existing classes
|
|
|
|
|
``builtin_function_or_method`` and ``method_descriptor``.
|
|
|
|
|
However, in the future, more classes may implement it.
|
|
|
|
|
|
2018-07-30 11:02:03 -04:00
|
|
|
|
**NOTE**: This PEP deals only with the Python/C API,
|
2018-06-19 17:55:39 -04:00
|
|
|
|
it does not affect the Python language or standard library.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Motivation
|
|
|
|
|
==========
|
|
|
|
|
|
2019-01-25 04:17:12 -05:00
|
|
|
|
The standard function/method classes ``builtin_function_or_method``
|
|
|
|
|
and ``method_descriptor`` allow very efficiently calling C code.
|
|
|
|
|
However, they are not subclassable, making them unsuitable for many applications:
|
|
|
|
|
for example, they offer limited introspection support
|
|
|
|
|
(signatures only using ``__text_signature__``, no arbitrary ``__qualname__``,
|
|
|
|
|
no ``inspect.getfile()``).
|
|
|
|
|
It's also not possible to store additional data to implement something like
|
|
|
|
|
``functools.partial`` or ``functools.lru_cache``.
|
|
|
|
|
So, there are many reasons why users would want to implement custom
|
|
|
|
|
function/method classes (in a duck-typing sense) in C.
|
|
|
|
|
Unfortunately, such custom classes are necessarily slower than
|
|
|
|
|
the standard CPython function classes:
|
|
|
|
|
the bytecode interpreter has various optimizations
|
|
|
|
|
which are specific to instances of
|
|
|
|
|
``builtin_function_or_method``, ``method_descriptor``, ``method`` and ``function``.
|
|
|
|
|
|
|
|
|
|
This PEP also allows to simplify existing code:
|
|
|
|
|
checks for ``builtin_function_or_method`` and ``method_descriptor``
|
2018-06-19 17:55:39 -04:00
|
|
|
|
could be replaced by simply checking for and using the C call protocol.
|
2019-01-25 04:17:12 -05:00
|
|
|
|
Future PEPs may implement the C call protocol for more classes,
|
|
|
|
|
enabling even further simplifications.
|
2018-06-19 17:55:39 -04:00
|
|
|
|
|
|
|
|
|
We also design the C call protocol such that it can easily
|
|
|
|
|
be extended with new features in the future.
|
|
|
|
|
|
2022-01-21 06:03:51 -05:00
|
|
|
|
For more background and motivation, see :pep:`579`.
|
2018-07-16 12:36:35 -04:00
|
|
|
|
|
|
|
|
|
|
2019-01-25 04:17:12 -05:00
|
|
|
|
Overview
|
|
|
|
|
========
|
2018-07-16 12:36:35 -04:00
|
|
|
|
|
|
|
|
|
Currently, CPython has multiple optimizations for fast calling
|
|
|
|
|
for a few specific function classes.
|
2019-01-25 04:17:12 -05:00
|
|
|
|
A good example is the implementation of the opcode ``CALL_FUNCTION``,
|
|
|
|
|
which has the following structure
|
|
|
|
|
(`see the actual code <https://github.com/python/cpython/blob/7a2368063f25746d4008a74aca0dc0b82f86ff7b/Python/ceval.c#L4592>`_)::
|
|
|
|
|
|
|
|
|
|
if (PyCFunction_Check(func)) {
|
|
|
|
|
return _PyCFunction_FastCallKeywords(func, stack, nargs, kwnames);
|
|
|
|
|
}
|
|
|
|
|
else if (Py_TYPE(func) == &PyMethodDescr_Type) {
|
|
|
|
|
return _PyMethodDescr_FastCallKeywords(func, stack, nargs, kwnames);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
if (PyMethod_Check(func) && PyMethod_GET_SELF(func) != NULL) {
|
|
|
|
|
/* ... */
|
|
|
|
|
}
|
|
|
|
|
if (PyFunction_Check(func)) {
|
|
|
|
|
return _PyFunction_FastCallKeywords(func, stack, nargs, kwnames);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
return _PyObject_FastCallKeywords(func, stack, nargs, kwnames);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Calling instances of these special-cased classes
|
|
|
|
|
using the ``tp_call`` slot is slower than using the optimizations.
|
|
|
|
|
The basic idea of this PEP is to enable such optimizations
|
|
|
|
|
for user C code, both as caller and as callee.
|
2018-07-16 12:36:35 -04:00
|
|
|
|
|
|
|
|
|
The existing class ``builtin_function_or_method`` and a few others
|
|
|
|
|
use a ``PyMethodDef`` structure for describing the underlying C function and its signature.
|
|
|
|
|
The first concrete change is that this is replaced by a new structure ``PyCCallDef``.
|
|
|
|
|
This stores some of the same information as a ``PyMethodDef``,
|
|
|
|
|
but with one important addition:
|
|
|
|
|
the "parent" of the function (the class or module where it is defined).
|
|
|
|
|
Note that ``PyMethodDef`` arrays are still used to construct
|
2018-06-19 17:55:39 -04:00
|
|
|
|
functions/methods but no longer for calling them.
|
|
|
|
|
|
2018-07-16 12:36:35 -04:00
|
|
|
|
Second, we want that every class can use such a ``PyCCallDef`` for optimizing calls,
|
|
|
|
|
so the ``PyTypeObject`` structure gains a ``tp_ccalloffset`` field
|
|
|
|
|
giving an offset to a ``PyCCallDef *`` in the object structure
|
|
|
|
|
and a flag ``Py_TPFLAGS_HAVE_CCALL`` indicating that ``tp_ccalloffset`` is valid.
|
|
|
|
|
|
|
|
|
|
Third, since we want to deal efficiently with unbound and bound methods too
|
2018-09-21 17:31:11 -04:00
|
|
|
|
(as opposed to only plain functions), we need to handle ``__self__`` in the protocol:
|
2018-07-16 12:36:35 -04:00
|
|
|
|
after the ``PyCCallDef *`` in the object structure,
|
|
|
|
|
there is a ``PyObject *self`` field.
|
|
|
|
|
These two fields together are referred to as a ``PyCCallRoot`` structure.
|
|
|
|
|
|
|
|
|
|
The new protocol for efficiently calling objects using these new structures
|
|
|
|
|
is called the "C call protocol".
|
2018-06-19 17:55:39 -04:00
|
|
|
|
|
2019-01-25 04:17:12 -05:00
|
|
|
|
**NOTE**: In this PEP, the phrases "unbound method" and "bound method"
|
|
|
|
|
refer to generic behavior, not to specific classes.
|
|
|
|
|
For example, an unbound method gets turned into a bound method
|
|
|
|
|
after applying ``__get__``.
|
|
|
|
|
|
2018-06-19 17:55:39 -04:00
|
|
|
|
|
|
|
|
|
New data structures
|
|
|
|
|
===================
|
|
|
|
|
|
|
|
|
|
The ``PyTypeObject`` structure gains a new field ``Py_ssize_t tp_ccalloffset``
|
|
|
|
|
and a new flag ``Py_TPFLAGS_HAVE_CCALL``.
|
|
|
|
|
If this flag is set, then ``tp_ccalloffset`` is assumed to be a valid
|
2018-09-21 17:31:11 -04:00
|
|
|
|
offset inside the object structure (similar to ``tp_dictoffset`` and ``tp_weaklistoffset``).
|
2018-06-19 17:55:39 -04:00
|
|
|
|
It must be a strictly positive integer.
|
2018-06-22 18:02:29 -04:00
|
|
|
|
At that offset, a ``PyCCallRoot`` structure appears::
|
2018-06-19 17:55:39 -04:00
|
|
|
|
|
|
|
|
|
typedef struct {
|
2019-04-01 15:55:23 -04:00
|
|
|
|
const PyCCallDef *cr_ccall;
|
|
|
|
|
PyObject *cr_self; /* __self__ argument for methods */
|
2018-06-22 18:02:29 -04:00
|
|
|
|
} PyCCallRoot;
|
2018-06-19 17:55:39 -04:00
|
|
|
|
|
|
|
|
|
The ``PyCCallDef`` structure contains everything needed to describe how
|
|
|
|
|
the function can be called::
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
2018-07-16 12:36:35 -04:00
|
|
|
|
uint32_t cc_flags;
|
|
|
|
|
PyCFunc cc_func; /* C function to call */
|
|
|
|
|
PyObject *cc_parent; /* class or module */
|
2018-06-19 17:55:39 -04:00
|
|
|
|
} PyCCallDef;
|
|
|
|
|
|
|
|
|
|
The reason for putting ``__self__`` outside of ``PyCCallDef``
|
|
|
|
|
is that ``PyCCallDef`` is not meant to be changed after creating the function.
|
|
|
|
|
A single ``PyCCallDef`` can be shared
|
|
|
|
|
by an unbound method and multiple bound methods.
|
|
|
|
|
This wouldn't work if we would put ``__self__`` inside that structure.
|
|
|
|
|
|
|
|
|
|
**NOTE**: unlike ``tp_dictoffset`` we do not allow negative numbers
|
|
|
|
|
for ``tp_ccalloffset`` to mean counting from the end.
|
|
|
|
|
There does not seem to be a use case for it and it would only complicate
|
|
|
|
|
the implementation.
|
|
|
|
|
|
|
|
|
|
Parent
|
|
|
|
|
------
|
|
|
|
|
|
|
|
|
|
The ``cc_parent`` field (accessed for example by a ``__parent__``
|
2018-10-04 07:00:08 -04:00
|
|
|
|
or ``__objclass__`` descriptor from Python code) can be any Python
|
|
|
|
|
object, or NULL.
|
|
|
|
|
Custom classes are free to set ``cc_parent`` to whatever they want.
|
|
|
|
|
It is only used by the C call protocol if the
|
|
|
|
|
``CCALL_OBJCLASS`` flag is set.
|
2018-06-19 17:55:39 -04:00
|
|
|
|
|
2018-10-04 07:00:08 -04:00
|
|
|
|
For methods of extension types, ``cc_parent`` points to the class
|
|
|
|
|
that defines the method (which may be a superclass of ``type(self)``).
|
2019-01-25 04:17:12 -05:00
|
|
|
|
This is currently non-trivial to retrieve from a method's code.
|
|
|
|
|
In the future, this can be used to access the module state via
|
2022-01-21 06:03:51 -05:00
|
|
|
|
the defining class. See the rationale of :pep:`573` for details.
|
2018-10-04 07:00:08 -04:00
|
|
|
|
|
|
|
|
|
When the flag ``CCALL_OBJCLASS`` is set (as it will be for methods of
|
|
|
|
|
extension types), ``cc_parent`` is used for type checks like the following::
|
2018-06-19 17:55:39 -04:00
|
|
|
|
|
|
|
|
|
>>> list.append({}, "x")
|
|
|
|
|
Traceback (most recent call last):
|
|
|
|
|
File "<stdin>", line 1, in <module>
|
|
|
|
|
TypeError: descriptor 'append' requires a 'list' object but received a 'dict'
|
|
|
|
|
|
2018-10-04 07:00:08 -04:00
|
|
|
|
For functions of modules, ``cc_parent`` is set to the module.
|
|
|
|
|
Currently, this is exactly the same as ``__self__``.
|
2018-08-03 15:08:57 -04:00
|
|
|
|
However, using ``__self__`` for the module is a quirk of the current implementation:
|
|
|
|
|
in the future, we want to allow functions which use ``__self__``
|
|
|
|
|
in the normal way, for implementing methods.
|
|
|
|
|
Such functions can still use ``cc_parent`` instead to refer to the module.
|
2018-06-19 17:55:39 -04:00
|
|
|
|
|
2018-10-04 07:00:08 -04:00
|
|
|
|
The parent would also typically be used to implement ``__qualname__``.
|
|
|
|
|
The new C API function ``PyCCall_GenericGetQualname()`` does exactly that.
|
|
|
|
|
|
2018-06-22 18:02:29 -04:00
|
|
|
|
Using tp_print
|
|
|
|
|
--------------
|
|
|
|
|
|
|
|
|
|
We propose to replace the existing unused field ``tp_print``
|
|
|
|
|
by ``tp_ccalloffset``.
|
|
|
|
|
Since ``Py_TPFLAGS_HAVE_CCALL`` would *not* be added to
|
|
|
|
|
``Py_TPFLAGS_DEFAULT``, this ensures full backwards compatibility for
|
|
|
|
|
existing extension modules setting ``tp_print``.
|
|
|
|
|
It also means that we can require that ``tp_ccalloffset`` is a valid
|
|
|
|
|
offset when ``Py_TPFLAGS_HAVE_CCALL`` is specified:
|
|
|
|
|
we do not need to check ``tp_ccalloffset != 0``.
|
|
|
|
|
In future Python versions, we may decide that ``tp_print``
|
|
|
|
|
becomes ``tp_ccalloffset`` unconditionally,
|
|
|
|
|
drop the ``Py_TPFLAGS_HAVE_CCALL`` flag and instead check for
|
|
|
|
|
``tp_ccalloffset != 0``.
|
|
|
|
|
|
2022-01-21 06:03:51 -05:00
|
|
|
|
**NOTE**: the exact layout of ``PyTypeObject`` is not part of the :pep:`stable ABI <384>`).
|
2018-09-21 17:31:11 -04:00
|
|
|
|
Therefore, changing the ``tp_print`` field from a ``printfunc`` (a function pointer)
|
|
|
|
|
to a ``Py_ssize_t`` should not be a problem,
|
|
|
|
|
even if this changes the memory layout of the ``PyTypeObject`` structure.
|
|
|
|
|
Moreover, on all systems for which binaries are commonly built
|
|
|
|
|
(Windows, Linux, macOS),
|
|
|
|
|
the size of ``printfunc`` and ``Py_ssize_t`` are the same,
|
|
|
|
|
so the issue of binary compatibility will not come up anyway.
|
|
|
|
|
|
2018-06-19 17:55:39 -04:00
|
|
|
|
|
|
|
|
|
The C call protocol
|
|
|
|
|
===================
|
|
|
|
|
|
|
|
|
|
We say that a class implements the C call protocol
|
|
|
|
|
if it has the ``Py_TPFLAGS_HAVE_CCALL`` flag set
|
|
|
|
|
(as explained above, it must then set ``tp_ccalloffset > 0``).
|
|
|
|
|
Such a class must implement ``__call__`` as described in this section
|
|
|
|
|
(in practice, this just means setting ``tp_call`` to ``PyCCall_Call``).
|
|
|
|
|
|
2018-08-03 15:08:57 -04:00
|
|
|
|
The ``cc_func`` field is a C function pointer,
|
|
|
|
|
which plays the same role as the existing ``ml_meth`` field of ``PyMethodDef``.
|
2018-06-19 17:55:39 -04:00
|
|
|
|
Its precise signature depends on flags.
|
2018-09-21 17:31:11 -04:00
|
|
|
|
The subset of flags influencing the signature of ``cc_func``
|
|
|
|
|
is given by the bitmask ``CCALL_SIGNATURE``.
|
2018-06-19 17:55:39 -04:00
|
|
|
|
Below are the possible values for ``cc_flags & CCALL_SIGNATURE``
|
|
|
|
|
together with the arguments that the C function takes.
|
|
|
|
|
The return value is always ``PyObject *``.
|
2018-07-30 11:02:03 -04:00
|
|
|
|
The following are analogous to the existing ``PyMethodDef``
|
2018-06-19 17:55:39 -04:00
|
|
|
|
signature flags:
|
|
|
|
|
|
2018-07-30 11:02:03 -04:00
|
|
|
|
- ``CCALL_VARARGS``:
|
|
|
|
|
``cc_func(PyObject *self, PyObject *args)``
|
2018-06-19 17:55:39 -04:00
|
|
|
|
|
2018-07-30 11:02:03 -04:00
|
|
|
|
- ``CCALL_VARARGS | CCALL_KEYWORDS``:
|
|
|
|
|
``cc_func(PyObject *self, PyObject *args, PyObject *kwds)``
|
2018-09-21 17:31:11 -04:00
|
|
|
|
(``kwds`` is either ``NULL`` or a dict; this dict must not be modified by the callee)
|
2018-06-19 17:55:39 -04:00
|
|
|
|
|
2018-07-30 11:02:03 -04:00
|
|
|
|
- ``CCALL_FASTCALL``:
|
|
|
|
|
``cc_func(PyObject *self, PyObject *const *args, Py_ssize_t nargs)``
|
2018-06-19 17:55:39 -04:00
|
|
|
|
|
2018-07-30 11:02:03 -04:00
|
|
|
|
- ``CCALL_FASTCALL | CCALL_KEYWORDS``:
|
|
|
|
|
``cc_func(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)``
|
2018-08-03 15:08:57 -04:00
|
|
|
|
(``kwnames`` is either ``NULL`` or a non-empty tuple of keyword names)
|
2018-06-19 17:55:39 -04:00
|
|
|
|
|
2018-07-30 11:02:03 -04:00
|
|
|
|
- ``CCALL_NOARGS``:
|
2018-08-03 15:08:57 -04:00
|
|
|
|
``cc_func(PyObject *self, PyObject *unused)`` (second argument is always ``NULL``)
|
2018-06-19 17:55:39 -04:00
|
|
|
|
|
2018-07-30 11:02:03 -04:00
|
|
|
|
- ``CCALL_O``:
|
|
|
|
|
``cc_func(PyObject *self, PyObject *arg)``
|
2018-06-19 17:55:39 -04:00
|
|
|
|
|
2019-04-01 15:55:23 -04:00
|
|
|
|
The flag ``CCALL_DEFARG`` may be combined with any of these.
|
2018-08-03 15:08:57 -04:00
|
|
|
|
If so, the C function takes an additional argument
|
2019-04-01 15:55:23 -04:00
|
|
|
|
as first argument before ``self``,
|
|
|
|
|
namely a const pointer to the ``PyCCallDef`` structure used for this call.
|
2018-06-19 17:55:39 -04:00
|
|
|
|
For example, we have the following signature:
|
|
|
|
|
|
2019-04-01 15:55:23 -04:00
|
|
|
|
- ``CCALL_DEFARG | CCALL_VARARGS``:
|
|
|
|
|
``cc_func(const PyCCallDef *def, PyObject *self, PyObject *args)``
|
2018-08-03 15:08:57 -04:00
|
|
|
|
|
2019-04-01 15:55:23 -04:00
|
|
|
|
One exception is ``CCALL_DEFARG | CCALL_NOARGS``:
|
2018-08-03 15:08:57 -04:00
|
|
|
|
the ``unused`` argument is dropped, so the signature becomes
|
|
|
|
|
|
2019-04-01 15:55:23 -04:00
|
|
|
|
- ``CCALL_DEFARG | CCALL_NOARGS``:
|
|
|
|
|
``cc_func(const PyCCallDef *def, PyObject *self)``
|
2018-06-19 17:55:39 -04:00
|
|
|
|
|
2019-04-01 15:55:23 -04:00
|
|
|
|
**NOTE**: unlike the existing ``METH_...`` flags,
|
2018-06-19 17:55:39 -04:00
|
|
|
|
the ``CCALL_...`` constants do not necessarily represent single bits.
|
2018-09-21 17:31:11 -04:00
|
|
|
|
So checking ``if (cc_flags & CCALL_VARARGS)`` is not a valid way
|
2018-06-19 17:55:39 -04:00
|
|
|
|
for checking the signature.
|
2018-09-21 17:31:11 -04:00
|
|
|
|
There are also no guarantees of binary compatibility for these flags
|
|
|
|
|
between Python versions.
|
|
|
|
|
This allows the implementation to choose the most efficient
|
|
|
|
|
numerical values of the flags.
|
|
|
|
|
In the reference implementation,
|
|
|
|
|
the legal values for ``cc_flags & CCALL_SIGNATURE`` form exactly the interval [0, …, 11].
|
|
|
|
|
This means that the compiler can easily
|
|
|
|
|
optimize a ``switch`` statement for those cases using a computed goto.
|
2018-06-19 17:55:39 -04:00
|
|
|
|
|
|
|
|
|
Checking __objclass__
|
|
|
|
|
---------------------
|
|
|
|
|
|
2018-06-22 18:02:29 -04:00
|
|
|
|
If the ``CCALL_OBJCLASS`` flag is set and if ``cr_self`` is NULL
|
2018-06-19 17:55:39 -04:00
|
|
|
|
(this is the case for unbound methods of extension types),
|
|
|
|
|
then a type check is done:
|
|
|
|
|
the function must be called with at least one positional argument
|
|
|
|
|
and the first (typically called ``self``) must be an instance of
|
|
|
|
|
``cc_parent`` (which must be a class).
|
|
|
|
|
If not, a ``TypeError`` is raised.
|
|
|
|
|
|
|
|
|
|
Self slicing
|
|
|
|
|
------------
|
|
|
|
|
|
2018-07-30 11:02:03 -04:00
|
|
|
|
If ``cr_self`` is not NULL or if the flag ``CCALL_SELFARG``
|
2018-06-19 17:55:39 -04:00
|
|
|
|
is not set in ``cc_flags``, then the argument passed as ``self``
|
2018-06-22 18:02:29 -04:00
|
|
|
|
is simply ``cr_self``.
|
2018-06-19 17:55:39 -04:00
|
|
|
|
|
2018-07-30 11:02:03 -04:00
|
|
|
|
If ``cr_self`` is NULL and the flag ``CCALL_SELFARG`` is set,
|
2018-07-07 18:49:16 -04:00
|
|
|
|
then the first positional argument is removed from
|
2018-09-21 17:31:11 -04:00
|
|
|
|
``args`` and instead passed as ``self`` argument to the C function.
|
2018-06-19 17:55:39 -04:00
|
|
|
|
Effectively, the first positional argument is treated as ``__self__``.
|
2018-07-07 18:49:16 -04:00
|
|
|
|
If there are no positional arguments, ``TypeError`` is raised.
|
2018-06-19 17:55:39 -04:00
|
|
|
|
|
2018-08-03 15:08:57 -04:00
|
|
|
|
This process is called "self slicing" and a function is said to have self
|
2018-07-30 11:02:03 -04:00
|
|
|
|
slicing if ``cr_self`` is NULL and ``CCALL_SELFARG`` is set.
|
2018-06-19 17:55:39 -04:00
|
|
|
|
|
2018-08-03 15:08:57 -04:00
|
|
|
|
Note that a ``CCALL_NOARGS`` function with self slicing effectively has
|
2018-06-19 17:55:39 -04:00
|
|
|
|
one argument, namely ``self``.
|
2018-08-03 15:08:57 -04:00
|
|
|
|
Analogously, a ``CCALL_O`` function with self slicing has two arguments.
|
2018-06-19 17:55:39 -04:00
|
|
|
|
|
2018-07-07 18:49:16 -04:00
|
|
|
|
Descriptor behavior
|
|
|
|
|
-------------------
|
2018-06-19 17:55:39 -04:00
|
|
|
|
|
|
|
|
|
Classes supporting the C call protocol
|
2018-07-07 18:49:16 -04:00
|
|
|
|
must implement the descriptor protocol in a specific way.
|
2018-09-21 17:31:11 -04:00
|
|
|
|
|
2018-07-07 18:49:16 -04:00
|
|
|
|
This is required for an efficient implementation of bound methods:
|
2018-09-21 17:31:11 -04:00
|
|
|
|
if other code can make assumptions on what ``__get__`` does,
|
|
|
|
|
it enables optimizations which would not be possible otherwise.
|
|
|
|
|
In particular, we want to allow sharing
|
|
|
|
|
the ``PyCCallDef`` structure between bound and unbound methods.
|
|
|
|
|
We also need a correct implementation of ``_PyObject_GetMethod``
|
2018-07-07 18:49:16 -04:00
|
|
|
|
which is used by the ``LOAD_METHOD``/``CALL_METHOD`` optimization.
|
2018-09-21 17:31:11 -04:00
|
|
|
|
|
2018-07-07 18:49:16 -04:00
|
|
|
|
First of all, if ``func`` supports the C call protocol,
|
2018-09-21 17:31:11 -04:00
|
|
|
|
then ``func.__set__`` and ``func.__delete__`` must not be implemented.
|
2018-07-07 18:49:16 -04:00
|
|
|
|
|
|
|
|
|
Second, ``func.__get__`` must behave as follows:
|
2018-06-19 17:55:39 -04:00
|
|
|
|
|
2018-06-22 18:02:29 -04:00
|
|
|
|
- If ``cr_self`` is not NULL, then ``__get__`` must be a no-op
|
2018-06-19 17:55:39 -04:00
|
|
|
|
in the sense that ``func.__get__(obj, cls)(*args, **kwds)``
|
|
|
|
|
behaves exactly the same as ``func(*args, **kwds)``.
|
|
|
|
|
It is also allowed for ``__get__`` to be not implemented at all.
|
|
|
|
|
|
2018-06-22 18:02:29 -04:00
|
|
|
|
- If ``cr_self`` is NULL, then ``func.__get__(obj, cls)(*args, **kwds)``
|
2018-06-19 17:55:39 -04:00
|
|
|
|
(with ``obj`` not None)
|
|
|
|
|
must be equivalent to ``func(obj, *args, **kwds)``.
|
2018-06-22 18:02:29 -04:00
|
|
|
|
In particular, ``__get__`` must be implemented in this case.
|
2018-09-21 17:31:11 -04:00
|
|
|
|
This is unrelated to `self slicing`_: ``obj`` may be passed
|
2018-06-19 17:55:39 -04:00
|
|
|
|
as ``self`` argument to the C function or it may be the first positional argument.
|
|
|
|
|
|
2018-06-22 18:02:29 -04:00
|
|
|
|
- If ``cr_self`` is NULL, then ``func.__get__(None, cls)(*args, **kwds)``
|
2018-06-19 17:55:39 -04:00
|
|
|
|
must be equivalent to ``func(*args, **kwds)``.
|
|
|
|
|
|
|
|
|
|
There are no restrictions on the object ``func.__get__(obj, cls)``.
|
|
|
|
|
The latter is not required to implement the C call protocol for example.
|
2018-09-21 17:31:11 -04:00
|
|
|
|
We only specify what ``func.__get__(obj, cls).__call__`` does.
|
2018-06-19 17:55:39 -04:00
|
|
|
|
|
|
|
|
|
For classes that do not care about ``__self__`` and ``__get__`` at all,
|
2018-06-22 18:02:29 -04:00
|
|
|
|
the easiest solution is to assign ``cr_self = Py_None``
|
2018-06-19 17:55:39 -04:00
|
|
|
|
(or any other non-NULL value).
|
|
|
|
|
|
2018-09-21 17:31:11 -04:00
|
|
|
|
The __name__ attribute
|
|
|
|
|
----------------------
|
2018-07-16 12:36:35 -04:00
|
|
|
|
|
|
|
|
|
The C call protocol requires that the function has a ``__name__``
|
|
|
|
|
attribute which is of type ``str`` (not a subclass).
|
|
|
|
|
|
2019-01-25 04:17:12 -05:00
|
|
|
|
Furthermore, the object returned by ``__name__`` must be stored somewhere;
|
|
|
|
|
it cannot be a temporary object.
|
2018-07-30 11:02:03 -04:00
|
|
|
|
This is required because ``PyEval_GetFuncName``
|
2019-01-25 04:17:12 -05:00
|
|
|
|
uses a borrowed reference to the ``__name__`` attribute
|
|
|
|
|
(see also [#badcapi]_).
|
2018-07-16 12:36:35 -04:00
|
|
|
|
|
2018-06-19 17:55:39 -04:00
|
|
|
|
Generic API functions
|
|
|
|
|
---------------------
|
|
|
|
|
|
2018-07-30 11:02:03 -04:00
|
|
|
|
This section lists the new public API functions or macros
|
|
|
|
|
dealing with the C call protocol.
|
2018-06-19 17:55:39 -04:00
|
|
|
|
|
|
|
|
|
- ``int PyCCall_Check(PyObject *op)``:
|
|
|
|
|
return true if ``op`` implements the C call protocol.
|
|
|
|
|
|
2018-07-07 18:49:16 -04:00
|
|
|
|
All the functions and macros below
|
|
|
|
|
apply to any instance supporting the C call protocol.
|
|
|
|
|
In other words, ``PyCCall_Check(func)`` must be true.
|
|
|
|
|
|
2018-07-30 11:02:03 -04:00
|
|
|
|
- ``PyObject *PyCCall_Call(PyObject *func, PyObject *args, PyObject *kwds)``:
|
2018-07-07 18:49:16 -04:00
|
|
|
|
call ``func`` with positional arguments ``args``
|
|
|
|
|
and keyword arguments ``kwds`` (``kwds`` may be NULL).
|
2018-06-19 17:55:39 -04:00
|
|
|
|
This function is meant to be put in the ``tp_call`` slot.
|
|
|
|
|
|
2018-09-21 17:31:11 -04:00
|
|
|
|
- ``PyObject *PyCCall_FastCall(PyObject *func, PyObject *const *args, Py_ssize_t nargs, PyObject *kwds)``:
|
2018-07-07 18:49:16 -04:00
|
|
|
|
call ``func`` with ``nargs`` positional arguments given by ``args[0]``, …, ``args[nargs-1]``.
|
2018-06-19 17:55:39 -04:00
|
|
|
|
The parameter ``kwds`` can be NULL (no keyword arguments),
|
|
|
|
|
a dict with ``name:value`` items or a tuple with keyword names.
|
|
|
|
|
In the latter case, the keyword values are stored in the ``args``
|
|
|
|
|
array, starting at ``args[nargs]``.
|
|
|
|
|
|
2018-07-07 18:49:16 -04:00
|
|
|
|
Macros to access the ``PyCCallRoot`` and ``PyCCallDef`` structures:
|
|
|
|
|
|
2019-04-01 15:55:23 -04:00
|
|
|
|
- ``const PyCCallRoot *PyCCall_CCALLROOT(PyObject *func)``:
|
2018-07-07 18:49:16 -04:00
|
|
|
|
pointer to the ``PyCCallRoot`` structure inside ``func``.
|
|
|
|
|
|
2019-04-01 15:55:23 -04:00
|
|
|
|
- ``const PyCCallDef *PyCCall_CCALLDEF(PyObject *func)``:
|
2018-07-07 18:49:16 -04:00
|
|
|
|
shorthand for ``PyCCall_CCALLROOT(func)->cr_ccall``.
|
2018-06-22 18:02:29 -04:00
|
|
|
|
|
2019-04-01 15:55:23 -04:00
|
|
|
|
- ``uint32_t PyCCall_FLAGS(PyObject *func)``:
|
2018-07-16 12:36:35 -04:00
|
|
|
|
shorthand for ``PyCCall_CCALLROOT(func)->cr_ccall->cc_flags``.
|
|
|
|
|
|
2018-07-30 11:02:03 -04:00
|
|
|
|
- ``PyObject *PyCCall_SELF(PyOject *func)``:
|
2018-07-07 18:49:16 -04:00
|
|
|
|
shorthand for ``PyCCall_CCALLROOT(func)->cr_self``.
|
2018-06-22 18:02:29 -04:00
|
|
|
|
|
2018-07-07 18:49:16 -04:00
|
|
|
|
Generic getters, meant to be put into the ``tp_getset`` array:
|
|
|
|
|
|
2018-07-30 11:02:03 -04:00
|
|
|
|
- ``PyObject *PyCCall_GenericGetParent(PyObject *func, void *closure)``:
|
2018-07-07 18:49:16 -04:00
|
|
|
|
return ``cc_parent``.
|
2018-06-22 18:02:29 -04:00
|
|
|
|
Raise ``AttributeError`` if ``cc_parent`` is NULL.
|
|
|
|
|
|
2018-07-30 11:02:03 -04:00
|
|
|
|
- ``PyObject *PyCCall_GenericGetQualname(PyObject *func, void *closure)``:
|
2018-06-22 18:02:29 -04:00
|
|
|
|
return a string suitable for using as ``__qualname__``.
|
|
|
|
|
This uses the ``__qualname__`` of ``cc_parent`` if possible.
|
2018-07-16 12:36:35 -04:00
|
|
|
|
It also uses the ``__name__`` attribute.
|
2018-06-22 18:02:29 -04:00
|
|
|
|
|
2018-06-19 17:55:39 -04:00
|
|
|
|
Profiling
|
|
|
|
|
---------
|
|
|
|
|
|
2018-07-16 12:36:35 -04:00
|
|
|
|
The profiling events
|
|
|
|
|
``c_call``, ``c_return`` and ``c_exception`` are only generated
|
|
|
|
|
when calling actual instances of ``builtin_function_or_method`` or ``method_descriptor``.
|
|
|
|
|
This is done for simplicity and also for backwards compatibility
|
|
|
|
|
(such that the profile function does not receive objects that it does not recognize).
|
|
|
|
|
In a future PEP, we may extend C-level profiling to arbitrary classes
|
|
|
|
|
implementing the C call protocol.
|
2018-06-19 17:55:39 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Changes to built-in functions and methods
|
|
|
|
|
=========================================
|
|
|
|
|
|
|
|
|
|
The reference implementation of this PEP changes
|
|
|
|
|
the existing classes ``builtin_function_or_method`` and ``method_descriptor``
|
|
|
|
|
to use the C call protocol.
|
2018-06-22 18:02:29 -04:00
|
|
|
|
In fact, those two classes are almost merged:
|
|
|
|
|
the implementation becomes very similar, but they remain separate classes
|
|
|
|
|
(mostly for backwards compatibility).
|
|
|
|
|
The ``PyCCallDef`` structure is simply stored
|
2018-06-19 17:55:39 -04:00
|
|
|
|
as part of the object structure.
|
2018-06-22 18:02:29 -04:00
|
|
|
|
Both classes use ``PyCFunctionObject`` as object structure.
|
2019-04-01 15:55:23 -04:00
|
|
|
|
This is the new layout for both classes:
|
|
|
|
|
|
|
|
|
|
.. _PyCFunctionObject:
|
|
|
|
|
|
|
|
|
|
::
|
2018-06-19 17:55:39 -04:00
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
PyObject_HEAD
|
|
|
|
|
PyCCallDef *m_ccall;
|
2018-07-16 12:36:35 -04:00
|
|
|
|
PyObject *m_self; /* Passed as 'self' arg to the C function */
|
|
|
|
|
PyCCallDef _ccalldef; /* Storage for m_ccall */
|
|
|
|
|
PyObject *m_name; /* __name__; str object (not NULL) */
|
|
|
|
|
PyObject *m_module; /* __module__; can be anything */
|
|
|
|
|
const char *m_doc; /* __text_signature__ and __doc__ */
|
|
|
|
|
PyObject *m_weakreflist; /* List of weak references */
|
2018-06-19 17:55:39 -04:00
|
|
|
|
} PyCFunctionObject;
|
|
|
|
|
|
2018-07-07 18:49:16 -04:00
|
|
|
|
For functions of a module and for unbound methods of extension types,
|
|
|
|
|
``m_ccall`` points to the ``_ccalldef`` field.
|
2018-06-22 18:02:29 -04:00
|
|
|
|
For bound methods, ``m_ccall`` points to the ``PyCCallDef``
|
2018-06-19 17:55:39 -04:00
|
|
|
|
of the unbound method.
|
|
|
|
|
|
2018-06-22 18:02:29 -04:00
|
|
|
|
**NOTE**: the new layout of ``method_descriptor`` changes it
|
2018-06-19 17:55:39 -04:00
|
|
|
|
such that it no longer starts with ``PyDescr_COMMON``.
|
2018-07-07 18:49:16 -04:00
|
|
|
|
This is purely an implementation detail and it should cause few (if any)
|
2018-06-19 17:55:39 -04:00
|
|
|
|
compatibility problems.
|
|
|
|
|
|
2018-06-22 18:02:29 -04:00
|
|
|
|
C API functions
|
|
|
|
|
---------------
|
|
|
|
|
|
2022-01-21 06:03:51 -05:00
|
|
|
|
The following function is added (also to the :pep:`stable ABI <384>`):
|
2018-06-22 18:02:29 -04:00
|
|
|
|
|
|
|
|
|
- ``PyObject * PyCFunction_ClsNew(PyTypeObject *cls, PyMethodDef *ml, PyObject *self, PyObject *module, PyObject *parent)``:
|
|
|
|
|
create a new object with object structure ``PyCFunctionObject`` and class ``cls``.
|
2018-08-03 15:08:57 -04:00
|
|
|
|
The entries of the ``PyMethodDef`` structure are used to construct
|
|
|
|
|
the new object, but the pointer to the ``PyMethodDef`` structure
|
|
|
|
|
is not stored.
|
2018-07-30 11:02:03 -04:00
|
|
|
|
The flags for the C call protocol are automatically determined in terms
|
|
|
|
|
of ``ml->ml_flags``, ``self`` and ``parent``.
|
|
|
|
|
|
|
|
|
|
The existing functions ``PyCFunction_New``, ``PyCFunction_NewEx`` and
|
|
|
|
|
``PyDescr_NewMethod`` are implemented in terms of ``PyCFunction_ClsNew``.
|
2018-06-22 18:02:29 -04:00
|
|
|
|
|
|
|
|
|
The undocumented functions ``PyCFunction_GetFlags``
|
2018-09-21 17:31:11 -04:00
|
|
|
|
and ``PyCFunction_GET_FLAGS`` are deprecated.
|
|
|
|
|
They are still artificially supported by storing the original ``METH_...``
|
|
|
|
|
flags in a bitfield inside ``cc_flags``.
|
|
|
|
|
Despite the fact that ``PyCFunction_GetFlags`` is technically
|
2022-01-21 06:03:51 -05:00
|
|
|
|
part of the :pep:`stable ABI <384>`,
|
2018-09-21 17:31:11 -04:00
|
|
|
|
it is highly unlikely to be used that way:
|
|
|
|
|
first of all, it is not even documented.
|
|
|
|
|
Second, the flag ``METH_FASTCALL``
|
|
|
|
|
is not part of the stable ABI but it is very common
|
|
|
|
|
(because of Argument Clinic).
|
|
|
|
|
So, if one cannot support ``METH_FASTCALL``,
|
|
|
|
|
it is hard to imagine a use case for ``PyCFunction_GetFlags``.
|
|
|
|
|
The fact that ``PyCFunction_GET_FLAGS`` and ``PyCFunction_GetFlags``
|
|
|
|
|
are not used at all by CPython outside of ``Objects/call.c``
|
|
|
|
|
further shows that these functions are not particularly useful.
|
2018-06-22 18:02:29 -04:00
|
|
|
|
|
2018-06-19 17:55:39 -04:00
|
|
|
|
|
|
|
|
|
Inheritance
|
|
|
|
|
===========
|
|
|
|
|
|
|
|
|
|
Extension types inherit the type flag ``Py_TPFLAGS_HAVE_CCALL``
|
|
|
|
|
and the value ``tp_ccalloffset`` from the base class,
|
|
|
|
|
provided that they implement ``tp_call`` and ``tp_descr_get``
|
|
|
|
|
the same way as the base class.
|
|
|
|
|
Heap types never inherit the C call protocol because
|
|
|
|
|
that would not be safe (heap types can be changed dynamically).
|
|
|
|
|
|
|
|
|
|
|
2018-07-07 18:49:16 -04:00
|
|
|
|
Performance
|
|
|
|
|
===========
|
|
|
|
|
|
|
|
|
|
This PEP should not impact the performance of existing code
|
|
|
|
|
(in the positive or negative sense).
|
|
|
|
|
It is meant to allow efficient new code to be written,
|
|
|
|
|
not to make existing code faster.
|
|
|
|
|
|
2018-07-30 11:02:03 -04:00
|
|
|
|
Here are a few pointers to the ``python-dev`` mailing list where
|
|
|
|
|
performance improvements are discussed:
|
|
|
|
|
|
|
|
|
|
- https://mail.python.org/pipermail/python-dev/2018-July/154571.html
|
|
|
|
|
|
|
|
|
|
- https://mail.python.org/pipermail/python-dev/2018-July/154740.html
|
|
|
|
|
|
|
|
|
|
- https://mail.python.org/pipermail/python-dev/2018-July/154775.html
|
|
|
|
|
|
2019-04-01 15:55:23 -04:00
|
|
|
|
- https://mail.python.org/pipermail/python-dev/2019-April/156954.html
|
|
|
|
|
|
2018-07-07 18:49:16 -04:00
|
|
|
|
|
|
|
|
|
Stable ABI
|
|
|
|
|
==========
|
|
|
|
|
|
2022-01-21 06:03:51 -05:00
|
|
|
|
The function ``PyCFunction_ClsNew`` is added to the :pep:`stable ABI <384>`.
|
2018-09-21 17:31:11 -04:00
|
|
|
|
|
2018-07-07 18:49:16 -04:00
|
|
|
|
None of the functions, structures or constants dealing with the C call protocol
|
2018-09-21 17:31:11 -04:00
|
|
|
|
are added to the stable ABI.
|
2018-07-07 18:49:16 -04:00
|
|
|
|
|
|
|
|
|
There are two reasons for this:
|
|
|
|
|
first of all, the most useful feature of the C call protocol is probably the
|
|
|
|
|
``METH_FASTCALL`` calling convention.
|
2022-01-21 06:03:51 -05:00
|
|
|
|
Given that this is not even part of the public API (see also :pep:`579`, issue 6),
|
2018-07-07 18:49:16 -04:00
|
|
|
|
it would be strange to add anything else from the C call protocol
|
|
|
|
|
to the stable ABI.
|
|
|
|
|
|
|
|
|
|
Second, we want the C call protocol to be extensible in the future.
|
|
|
|
|
By not adding anything to the stable ABI,
|
|
|
|
|
we are free to do that without restrictions.
|
|
|
|
|
|
|
|
|
|
|
2018-06-19 17:55:39 -04:00
|
|
|
|
Backwards compatibility
|
|
|
|
|
=======================
|
|
|
|
|
|
2018-07-30 11:02:03 -04:00
|
|
|
|
There is no difference at all for the Python interface,
|
|
|
|
|
nor for the documented C API
|
2018-06-19 17:55:39 -04:00
|
|
|
|
(in the sense that all functions remain supported with the same functionality).
|
|
|
|
|
|
2018-09-21 17:31:11 -04:00
|
|
|
|
The only potential breakage is with C code
|
2018-06-22 18:02:29 -04:00
|
|
|
|
which accesses the internals of ``PyCFunctionObject`` and ``PyMethodDescrObject``.
|
2018-06-19 17:55:39 -04:00
|
|
|
|
We expect very few problems because of this.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Rationale
|
|
|
|
|
=========
|
|
|
|
|
|
|
|
|
|
Why is this better than PEP 575?
|
|
|
|
|
--------------------------------
|
|
|
|
|
|
2022-01-21 06:03:51 -05:00
|
|
|
|
One of the major complaints of :pep:`575` was that is was coupling
|
2018-06-19 17:55:39 -04:00
|
|
|
|
functionality (the calling and introspection protocol)
|
|
|
|
|
with the class hierarchy:
|
|
|
|
|
a class could only benefit from the new features
|
|
|
|
|
if it was a subclass of ``base_function``.
|
|
|
|
|
It may be difficult for existing classes to do that
|
|
|
|
|
because they may have other constraints on the layout of the C object structure,
|
|
|
|
|
coming from an existing base class or implementation details.
|
2022-01-21 06:03:51 -05:00
|
|
|
|
For example, ``functools.lru_cache`` cannot implement :pep:`575` as-is.
|
2018-06-19 17:55:39 -04:00
|
|
|
|
|
|
|
|
|
It also complicated the implementation precisely because changes
|
|
|
|
|
were needed both in the implementation details and in the class hierarchy.
|
|
|
|
|
|
|
|
|
|
The current PEP does not have these problems.
|
|
|
|
|
|
|
|
|
|
Why store the function pointer in the instance?
|
|
|
|
|
-----------------------------------------------
|
|
|
|
|
|
|
|
|
|
The actual information needed for calling an object
|
|
|
|
|
is stored in the instance (in the ``PyCCallDef`` structure)
|
|
|
|
|
instead of the class.
|
|
|
|
|
This is different from the ``tp_call`` slot or earlier attempts
|
|
|
|
|
at implementing a ``tp_fastcall`` slot [#bpo29259]_.
|
|
|
|
|
|
|
|
|
|
The main use case is built-in functions and methods.
|
|
|
|
|
For those, the C function to be called does depend on the instance.
|
|
|
|
|
|
2018-07-07 18:49:16 -04:00
|
|
|
|
Note that the current protocol makes it easy to support the case
|
2018-06-19 17:55:39 -04:00
|
|
|
|
where the same C function is called for all instances:
|
|
|
|
|
just use a single static ``PyCCallDef`` structure for every instance.
|
|
|
|
|
|
2018-07-07 18:49:16 -04:00
|
|
|
|
Why CCALL_OBJCLASS?
|
|
|
|
|
-------------------
|
|
|
|
|
|
|
|
|
|
The flag ``CCALL_OBJCLASS`` is meant to support various cases
|
|
|
|
|
where the class of a ``self`` argument must be checked, such as::
|
|
|
|
|
|
|
|
|
|
>>> list.append({}, None)
|
|
|
|
|
Traceback (most recent call last):
|
|
|
|
|
File "<stdin>", line 1, in <module>
|
|
|
|
|
TypeError: append() requires a 'list' object but received a 'dict'
|
|
|
|
|
|
|
|
|
|
>>> list.__len__({})
|
|
|
|
|
Traceback (most recent call last):
|
|
|
|
|
File "<stdin>", line 1, in <module>
|
|
|
|
|
TypeError: descriptor '__len__' requires a 'list' object but received a 'dict'
|
|
|
|
|
|
|
|
|
|
>>> float.__dict__["fromhex"](list, "0xff")
|
|
|
|
|
Traceback (most recent call last):
|
|
|
|
|
File "<stdin>", line 1, in <module>
|
|
|
|
|
TypeError: descriptor 'fromhex' for type 'float' doesn't apply to type 'list'
|
|
|
|
|
|
|
|
|
|
In the reference implementation, only the first of these uses the new code.
|
|
|
|
|
The other examples show that these kind of checks appear
|
|
|
|
|
in multiple places, so it makes sense to add generic support for them.
|
|
|
|
|
|
2018-07-30 11:02:03 -04:00
|
|
|
|
Why CCALL_SELFARG?
|
|
|
|
|
------------------
|
2018-07-07 18:49:16 -04:00
|
|
|
|
|
2018-07-30 11:02:03 -04:00
|
|
|
|
The flag ``CCALL_SELFARG`` and the concept of self slicing
|
2018-07-07 18:49:16 -04:00
|
|
|
|
are needed to support methods:
|
|
|
|
|
the C function should not care
|
|
|
|
|
whether it is called as unbound method or as bound method.
|
|
|
|
|
In both cases, there should be a ``self`` argument
|
|
|
|
|
and this is simply the first positional argument of an unbound method call.
|
|
|
|
|
|
|
|
|
|
For example, ``list.append`` is a ``METH_O`` method.
|
|
|
|
|
Both the calls ``list.append([], 42)`` and ``[].append(42)`` should
|
|
|
|
|
translate to the C call ``list_append([], 42)``.
|
|
|
|
|
|
|
|
|
|
Thanks to the proposed C call protocol, we can support this in such a way
|
|
|
|
|
that both the unbound and the bound method share a ``PyCCallDef``
|
2018-07-30 11:02:03 -04:00
|
|
|
|
structure (with the ``CCALL_SELFARG`` flag set).
|
2018-07-07 18:49:16 -04:00
|
|
|
|
|
2018-09-21 17:31:11 -04:00
|
|
|
|
So, ``CCALL_SELFARG`` has two advantages:
|
|
|
|
|
there is no extra layer of indirection for calling methods
|
2018-07-07 18:49:16 -04:00
|
|
|
|
and constructing bound methods does not require setting up a ``PyCCallDef`` structure.
|
|
|
|
|
|
2018-09-21 17:31:11 -04:00
|
|
|
|
Another minor advantage is that we could
|
|
|
|
|
make the error messages for a wrong call signature
|
|
|
|
|
more uniform between Python methods and built-in methods.
|
|
|
|
|
In the following example, Python is undecided whether
|
2019-01-25 04:17:12 -05:00
|
|
|
|
a method takes 1 or 2 arguments::
|
2018-09-21 17:31:11 -04:00
|
|
|
|
|
|
|
|
|
>>> class List(list):
|
|
|
|
|
... def myappend(self, item):
|
|
|
|
|
... self.append(item)
|
|
|
|
|
>>> List().myappend(1, 2)
|
|
|
|
|
Traceback (most recent call last):
|
|
|
|
|
File "<stdin>", line 1, in <module>
|
|
|
|
|
TypeError: myappend() takes 2 positional arguments but 3 were given
|
|
|
|
|
>>> List().append(1, 2)
|
|
|
|
|
Traceback (most recent call last):
|
|
|
|
|
File "<stdin>", line 1, in <module>
|
|
|
|
|
TypeError: append() takes exactly one argument (2 given)
|
|
|
|
|
|
|
|
|
|
It is currently impossible for ``PyCFunction_Call``
|
|
|
|
|
to know the actual number of user-visible arguments
|
|
|
|
|
since it cannot distinguish at runtime between
|
|
|
|
|
a function (without ``self`` argument) and a bound method (with ``self`` argument).
|
|
|
|
|
The ``CCALL_SELFARG`` flag makes this difference explicit.
|
|
|
|
|
|
2019-04-01 15:55:23 -04:00
|
|
|
|
Why CCALL_DEFARG?
|
|
|
|
|
-----------------
|
|
|
|
|
|
|
|
|
|
The flag ``CCALL_DEFARG`` gives the callee access to the ``PyCCallDef *``.
|
|
|
|
|
There are various use cases for this:
|
|
|
|
|
|
2022-01-21 06:03:51 -05:00
|
|
|
|
1. The callee can use the ``cc_parent`` field, which is useful for :pep:`573`.
|
2019-04-01 15:55:23 -04:00
|
|
|
|
|
|
|
|
|
2. Applications are free to extend the ``PyCCallDef`` structure with user-defined
|
|
|
|
|
fields, which can then be accessed analogously.
|
|
|
|
|
|
|
|
|
|
3. In the case where the ``PyCCallDef`` structure
|
|
|
|
|
is part of the object structure
|
|
|
|
|
(this is true for example for `PyCFunctionObject`_),
|
|
|
|
|
an appropriate offset can be subtracted from the ``PyCCallDef`` pointer
|
|
|
|
|
to get a pointer to the callable object defining that ``PyCCallDef``.
|
|
|
|
|
|
|
|
|
|
An earlier version of this PEP defined a flag ``CCALL_FUNCARG``
|
|
|
|
|
instead of ``CCALL_DEFARG`` which would pass the callable object
|
|
|
|
|
to the callee.
|
|
|
|
|
This had similar use cases, but there was some ambiguity for
|
|
|
|
|
bound methods: should the "callable object" be the bound method
|
|
|
|
|
object or the original function wrapped by the method?
|
|
|
|
|
By passing the ``PyCCallDef *`` instead, this ambiguity is gone
|
|
|
|
|
since the bound method uses the ``PyCCallDef *`` from the wrapped function.
|
2018-09-21 17:31:11 -04:00
|
|
|
|
|
2018-06-22 18:02:29 -04:00
|
|
|
|
Replacing tp_print
|
|
|
|
|
------------------
|
|
|
|
|
|
2018-07-07 18:49:16 -04:00
|
|
|
|
We repurpose ``tp_print`` as ``tp_ccalloffset`` because this makes
|
2018-06-22 18:02:29 -04:00
|
|
|
|
it easier for external projects to backport the C call protocol
|
|
|
|
|
to earlier Python versions.
|
|
|
|
|
In particular, the Cython project has shown interest in doing that
|
|
|
|
|
(see https://mail.python.org/pipermail/python-dev/2018-June/153927.html).
|
|
|
|
|
|
2018-06-19 17:55:39 -04:00
|
|
|
|
|
2018-07-16 12:36:35 -04:00
|
|
|
|
Alternative suggestions
|
|
|
|
|
=======================
|
|
|
|
|
|
2022-01-21 06:03:51 -05:00
|
|
|
|
:pep:`576` is an alternative approach to solving the same problem as this PEP.
|
2018-07-16 12:36:35 -04:00
|
|
|
|
See https://mail.python.org/pipermail/python-dev/2018-July/154238.html
|
2022-01-21 06:03:51 -05:00
|
|
|
|
for comments on the difference between :pep:`576` and :pep:`580`.
|
2018-07-16 12:36:35 -04:00
|
|
|
|
|
|
|
|
|
|
2019-01-25 04:17:12 -05:00
|
|
|
|
Discussion
|
|
|
|
|
==========
|
|
|
|
|
|
|
|
|
|
Links to threads on the ``python-dev`` mailing list
|
|
|
|
|
where this PEP has been discussed:
|
|
|
|
|
|
|
|
|
|
- https://mail.python.org/pipermail/python-dev/2018-June/153938.html
|
|
|
|
|
|
|
|
|
|
- https://mail.python.org/pipermail/python-dev/2018-June/153984.html
|
|
|
|
|
|
|
|
|
|
- https://mail.python.org/pipermail/python-dev/2018-July/154238.html
|
|
|
|
|
|
|
|
|
|
- https://mail.python.org/pipermail/python-dev/2018-July/154470.html
|
|
|
|
|
|
|
|
|
|
- https://mail.python.org/pipermail/python-dev/2018-July/154571.html
|
|
|
|
|
|
|
|
|
|
- https://mail.python.org/pipermail/python-dev/2018-September/155166.html
|
|
|
|
|
|
|
|
|
|
- https://mail.python.org/pipermail/python-dev/2018-October/155403.html
|
|
|
|
|
|
2019-04-01 15:55:23 -04:00
|
|
|
|
- https://mail.python.org/pipermail/python-dev/2019-March/156853.html
|
|
|
|
|
|
|
|
|
|
- https://mail.python.org/pipermail/python-dev/2019-March/156879.html
|
|
|
|
|
|
2019-01-25 04:17:12 -05:00
|
|
|
|
|
2018-06-19 17:55:39 -04:00
|
|
|
|
Reference implementation
|
|
|
|
|
========================
|
|
|
|
|
|
2018-07-07 18:49:16 -04:00
|
|
|
|
The reference implementation can be found at
|
2018-06-22 18:02:29 -04:00
|
|
|
|
https://github.com/jdemeyer/cpython/tree/pep580
|
2018-06-19 17:55:39 -04:00
|
|
|
|
|
2019-04-01 15:55:23 -04:00
|
|
|
|
For an example of using the C call protocol,
|
2022-01-21 06:03:51 -05:00
|
|
|
|
the following branch implements ``functools.lru_cache`` using :pep:`580`:
|
2019-04-01 15:55:23 -04:00
|
|
|
|
https://github.com/jdemeyer/cpython/tree/lru580
|
|
|
|
|
|
2018-06-19 17:55:39 -04:00
|
|
|
|
|
|
|
|
|
References
|
|
|
|
|
==========
|
|
|
|
|
|
|
|
|
|
.. [#bpo29259] Add tp_fastcall to PyTypeObject: support FASTCALL calling convention for all callable objects,
|
|
|
|
|
https://bugs.python.org/issue29259
|
|
|
|
|
|
2019-01-25 04:17:12 -05:00
|
|
|
|
.. [#badcapi] Bad C API,
|
|
|
|
|
https://pythoncapi.readthedocs.io/bad_api.html#bad-c-api
|
2018-07-16 12:36:35 -04:00
|
|
|
|
|
2018-06-19 17:55:39 -04:00
|
|
|
|
Copyright
|
|
|
|
|
=========
|
|
|
|
|
|
|
|
|
|
This document has been placed in the public domain.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
..
|
|
|
|
|
Local Variables:
|
|
|
|
|
mode: indented-text
|
|
|
|
|
indent-tabs-mode: nil
|
|
|
|
|
sentence-end-double-space: t
|
|
|
|
|
fill-column: 70
|
|
|
|
|
coding: utf-8
|
|
|
|
|
End:
|