peps/pep-0580/index.html

862 lines
82 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 580 The C call protocol | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0580/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 580 The C call protocol | peps.python.org'>
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0580/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="Python Enhancement Proposals (PEPs)">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 580</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 580 The C call protocol</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Jeroen Demeyer &lt;J.Demeyer&#32;&#97;t&#32;UGent.be&gt;</dd>
<dt class="field-even">BDFL-Delegate<span class="colon">:</span></dt>
<dd class="field-even">Petr Viktorin</dd>
<dt class="field-odd">Status<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Formally declined and will not be accepted">Rejected</abbr></dd>
<dt class="field-even">Type<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-odd">Created<span class="colon">:</span></dt>
<dd class="field-odd">14-Jun-2018</dd>
<dt class="field-even">Python-Version<span class="colon">:</span></dt>
<dd class="field-even">3.8</dd>
<dt class="field-odd">Post-History<span class="colon">:</span></dt>
<dd class="field-odd">20-Jun-2018, 22-Jun-2018, 16-Jul-2018</dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#rejection-notice">Rejection Notice</a></li>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#motivation">Motivation</a></li>
<li><a class="reference internal" href="#overview">Overview</a></li>
<li><a class="reference internal" href="#new-data-structures">New data structures</a><ul>
<li><a class="reference internal" href="#parent">Parent</a></li>
<li><a class="reference internal" href="#using-tp-print">Using tp_print</a></li>
</ul>
</li>
<li><a class="reference internal" href="#the-c-call-protocol">The C call protocol</a><ul>
<li><a class="reference internal" href="#checking-objclass">Checking __objclass__</a></li>
<li><a class="reference internal" href="#self-slicing">Self slicing</a></li>
<li><a class="reference internal" href="#descriptor-behavior">Descriptor behavior</a></li>
<li><a class="reference internal" href="#the-name-attribute">The __name__ attribute</a></li>
<li><a class="reference internal" href="#generic-api-functions">Generic API functions</a></li>
<li><a class="reference internal" href="#profiling">Profiling</a></li>
</ul>
</li>
<li><a class="reference internal" href="#changes-to-built-in-functions-and-methods">Changes to built-in functions and methods</a><ul>
<li><a class="reference internal" href="#c-api-functions">C API functions</a></li>
</ul>
</li>
<li><a class="reference internal" href="#inheritance">Inheritance</a></li>
<li><a class="reference internal" href="#performance">Performance</a></li>
<li><a class="reference internal" href="#stable-abi">Stable ABI</a></li>
<li><a class="reference internal" href="#backwards-compatibility">Backwards compatibility</a></li>
<li><a class="reference internal" href="#rationale">Rationale</a><ul>
<li><a class="reference internal" href="#why-is-this-better-than-pep-575">Why is this better than PEP 575?</a></li>
<li><a class="reference internal" href="#why-store-the-function-pointer-in-the-instance">Why store the function pointer in the instance?</a></li>
<li><a class="reference internal" href="#why-ccall-objclass">Why CCALL_OBJCLASS?</a></li>
<li><a class="reference internal" href="#why-ccall-selfarg">Why CCALL_SELFARG?</a></li>
<li><a class="reference internal" href="#why-ccall-defarg">Why CCALL_DEFARG?</a></li>
<li><a class="reference internal" href="#replacing-tp-print">Replacing tp_print</a></li>
</ul>
</li>
<li><a class="reference internal" href="#alternative-suggestions">Alternative suggestions</a></li>
<li><a class="reference internal" href="#discussion">Discussion</a></li>
<li><a class="reference internal" href="#reference-implementation">Reference implementation</a></li>
<li><a class="reference internal" href="#references">References</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
</details></section>
<section id="rejection-notice">
<h2><a class="toc-backref" href="#rejection-notice" role="doc-backlink">Rejection Notice</a></h2>
<p>This PEP is rejected in favor of <a class="pep reference internal" href="../pep-0590/" title="PEP 590 Vectorcall: a fast calling protocol for CPython">PEP 590</a>, which proposes a simpler public
C API for callable objects.</p>
</section>
<section id="abstract">
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
<p>A new “C call” protocol is proposed.
It is meant for classes representing functions or methods
which need to implement fast calling.
The goal is to generalize all existing optimizations for built-in functions
to arbitrary extension types.</p>
<p>In the reference implementation,
this new protocol is used for the existing classes
<code class="docutils literal notranslate"><span class="pre">builtin_function_or_method</span></code> and <code class="docutils literal notranslate"><span class="pre">method_descriptor</span></code>.
However, in the future, more classes may implement it.</p>
<p><strong>NOTE</strong>: This PEP deals only with the Python/C API,
it does not affect the Python language or standard library.</p>
</section>
<section id="motivation">
<h2><a class="toc-backref" href="#motivation" role="doc-backlink">Motivation</a></h2>
<p>The standard function/method classes <code class="docutils literal notranslate"><span class="pre">builtin_function_or_method</span></code>
and <code class="docutils literal notranslate"><span class="pre">method_descriptor</span></code> 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 <code class="docutils literal notranslate"><span class="pre">__text_signature__</span></code>, no arbitrary <code class="docutils literal notranslate"><span class="pre">__qualname__</span></code>,
no <code class="docutils literal notranslate"><span class="pre">inspect.getfile()</span></code>).
Its also not possible to store additional data to implement something like
<code class="docutils literal notranslate"><span class="pre">functools.partial</span></code> or <code class="docutils literal notranslate"><span class="pre">functools.lru_cache</span></code>.
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
<code class="docutils literal notranslate"><span class="pre">builtin_function_or_method</span></code>, <code class="docutils literal notranslate"><span class="pre">method_descriptor</span></code>, <code class="docutils literal notranslate"><span class="pre">method</span></code> and <code class="docutils literal notranslate"><span class="pre">function</span></code>.</p>
<p>This PEP also allows to simplify existing code:
checks for <code class="docutils literal notranslate"><span class="pre">builtin_function_or_method</span></code> and <code class="docutils literal notranslate"><span class="pre">method_descriptor</span></code>
could be replaced by simply checking for and using the C call protocol.
Future PEPs may implement the C call protocol for more classes,
enabling even further simplifications.</p>
<p>We also design the C call protocol such that it can easily
be extended with new features in the future.</p>
<p>For more background and motivation, see <a class="pep reference internal" href="../pep-0579/" title="PEP 579 Refactoring C functions and methods">PEP 579</a>.</p>
</section>
<section id="overview">
<h2><a class="toc-backref" href="#overview" role="doc-backlink">Overview</a></h2>
<p>Currently, CPython has multiple optimizations for fast calling
for a few specific function classes.
A good example is the implementation of the opcode <code class="docutils literal notranslate"><span class="pre">CALL_FUNCTION</span></code>,
which has the following structure
(<a class="reference external" href="https://github.com/python/cpython/blob/7a2368063f25746d4008a74aca0dc0b82f86ff7b/Python/ceval.c#L4592">see the actual code</a>):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="p">(</span><span class="n">PyCFunction_Check</span><span class="p">(</span><span class="n">func</span><span class="p">))</span> <span class="p">{</span>
<span class="k">return</span> <span class="n">_PyCFunction_FastCallKeywords</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="n">stack</span><span class="p">,</span> <span class="n">nargs</span><span class="p">,</span> <span class="n">kwnames</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">Py_TYPE</span><span class="p">(</span><span class="n">func</span><span class="p">)</span> <span class="o">==</span> <span class="o">&amp;</span><span class="n">PyMethodDescr_Type</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="n">_PyMethodDescr_FastCallKeywords</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="n">stack</span><span class="p">,</span> <span class="n">nargs</span><span class="p">,</span> <span class="n">kwnames</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">else</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="n">PyMethod_Check</span><span class="p">(</span><span class="n">func</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="n">PyMethod_GET_SELF</span><span class="p">(</span><span class="n">func</span><span class="p">)</span> <span class="o">!=</span> <span class="n">NULL</span><span class="p">)</span> <span class="p">{</span>
<span class="o">/*</span> <span class="o">...</span> <span class="o">*/</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="n">PyFunction_Check</span><span class="p">(</span><span class="n">func</span><span class="p">))</span> <span class="p">{</span>
<span class="k">return</span> <span class="n">_PyFunction_FastCallKeywords</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="n">stack</span><span class="p">,</span> <span class="n">nargs</span><span class="p">,</span> <span class="n">kwnames</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">else</span> <span class="p">{</span>
<span class="k">return</span> <span class="n">_PyObject_FastCallKeywords</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="n">stack</span><span class="p">,</span> <span class="n">nargs</span><span class="p">,</span> <span class="n">kwnames</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
</div>
<p>Calling instances of these special-cased classes
using the <code class="docutils literal notranslate"><span class="pre">tp_call</span></code> 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.</p>
<p>The existing class <code class="docutils literal notranslate"><span class="pre">builtin_function_or_method</span></code> and a few others
use a <code class="docutils literal notranslate"><span class="pre">PyMethodDef</span></code> structure for describing the underlying C function and its signature.
The first concrete change is that this is replaced by a new structure <code class="docutils literal notranslate"><span class="pre">PyCCallDef</span></code>.
This stores some of the same information as a <code class="docutils literal notranslate"><span class="pre">PyMethodDef</span></code>,
but with one important addition:
the “parent” of the function (the class or module where it is defined).
Note that <code class="docutils literal notranslate"><span class="pre">PyMethodDef</span></code> arrays are still used to construct
functions/methods but no longer for calling them.</p>
<p>Second, we want that every class can use such a <code class="docutils literal notranslate"><span class="pre">PyCCallDef</span></code> for optimizing calls,
so the <code class="docutils literal notranslate"><span class="pre">PyTypeObject</span></code> structure gains a <code class="docutils literal notranslate"><span class="pre">tp_ccalloffset</span></code> field
giving an offset to a <code class="docutils literal notranslate"><span class="pre">PyCCallDef</span> <span class="pre">*</span></code> in the object structure
and a flag <code class="docutils literal notranslate"><span class="pre">Py_TPFLAGS_HAVE_CCALL</span></code> indicating that <code class="docutils literal notranslate"><span class="pre">tp_ccalloffset</span></code> is valid.</p>
<p>Third, since we want to deal efficiently with unbound and bound methods too
(as opposed to only plain functions), we need to handle <code class="docutils literal notranslate"><span class="pre">__self__</span></code> in the protocol:
after the <code class="docutils literal notranslate"><span class="pre">PyCCallDef</span> <span class="pre">*</span></code> in the object structure,
there is a <code class="docutils literal notranslate"><span class="pre">PyObject</span> <span class="pre">*self</span></code> field.
These two fields together are referred to as a <code class="docutils literal notranslate"><span class="pre">PyCCallRoot</span></code> structure.</p>
<p>The new protocol for efficiently calling objects using these new structures
is called the “C call protocol”.</p>
<p><strong>NOTE</strong>: 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 <code class="docutils literal notranslate"><span class="pre">__get__</span></code>.</p>
</section>
<section id="new-data-structures">
<h2><a class="toc-backref" href="#new-data-structures" role="doc-backlink">New data structures</a></h2>
<p>The <code class="docutils literal notranslate"><span class="pre">PyTypeObject</span></code> structure gains a new field <code class="docutils literal notranslate"><span class="pre">Py_ssize_t</span> <span class="pre">tp_ccalloffset</span></code>
and a new flag <code class="docutils literal notranslate"><span class="pre">Py_TPFLAGS_HAVE_CCALL</span></code>.
If this flag is set, then <code class="docutils literal notranslate"><span class="pre">tp_ccalloffset</span></code> is assumed to be a valid
offset inside the object structure (similar to <code class="docutils literal notranslate"><span class="pre">tp_dictoffset</span></code> and <code class="docutils literal notranslate"><span class="pre">tp_weaklistoffset</span></code>).
It must be a strictly positive integer.
At that offset, a <code class="docutils literal notranslate"><span class="pre">PyCCallRoot</span></code> structure appears:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">typedef</span> <span class="n">struct</span> <span class="p">{</span>
<span class="n">const</span> <span class="n">PyCCallDef</span> <span class="o">*</span><span class="n">cr_ccall</span><span class="p">;</span>
<span class="n">PyObject</span> <span class="o">*</span><span class="n">cr_self</span><span class="p">;</span> <span class="o">/*</span> <span class="vm">__self__</span> <span class="n">argument</span> <span class="k">for</span> <span class="n">methods</span> <span class="o">*/</span>
<span class="p">}</span> <span class="n">PyCCallRoot</span><span class="p">;</span>
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">PyCCallDef</span></code> structure contains everything needed to describe how
the function can be called:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">typedef</span> <span class="n">struct</span> <span class="p">{</span>
<span class="n">uint32_t</span> <span class="n">cc_flags</span><span class="p">;</span>
<span class="n">PyCFunc</span> <span class="n">cc_func</span><span class="p">;</span> <span class="o">/*</span> <span class="n">C</span> <span class="n">function</span> <span class="n">to</span> <span class="n">call</span> <span class="o">*/</span>
<span class="n">PyObject</span> <span class="o">*</span><span class="n">cc_parent</span><span class="p">;</span> <span class="o">/*</span> <span class="k">class</span> <span class="nc">or</span> <span class="n">module</span> <span class="o">*/</span>
<span class="p">}</span> <span class="n">PyCCallDef</span><span class="p">;</span>
</pre></div>
</div>
<p>The reason for putting <code class="docutils literal notranslate"><span class="pre">__self__</span></code> outside of <code class="docutils literal notranslate"><span class="pre">PyCCallDef</span></code>
is that <code class="docutils literal notranslate"><span class="pre">PyCCallDef</span></code> is not meant to be changed after creating the function.
A single <code class="docutils literal notranslate"><span class="pre">PyCCallDef</span></code> can be shared
by an unbound method and multiple bound methods.
This wouldnt work if we would put <code class="docutils literal notranslate"><span class="pre">__self__</span></code> inside that structure.</p>
<p><strong>NOTE</strong>: unlike <code class="docutils literal notranslate"><span class="pre">tp_dictoffset</span></code> we do not allow negative numbers
for <code class="docutils literal notranslate"><span class="pre">tp_ccalloffset</span></code> to mean counting from the end.
There does not seem to be a use case for it and it would only complicate
the implementation.</p>
<section id="parent">
<h3><a class="toc-backref" href="#parent" role="doc-backlink">Parent</a></h3>
<p>The <code class="docutils literal notranslate"><span class="pre">cc_parent</span></code> field (accessed for example by a <code class="docutils literal notranslate"><span class="pre">__parent__</span></code>
or <code class="docutils literal notranslate"><span class="pre">__objclass__</span></code> descriptor from Python code) can be any Python
object, or NULL.
Custom classes are free to set <code class="docutils literal notranslate"><span class="pre">cc_parent</span></code> to whatever they want.
It is only used by the C call protocol if the
<code class="docutils literal notranslate"><span class="pre">CCALL_OBJCLASS</span></code> flag is set.</p>
<p>For methods of extension types, <code class="docutils literal notranslate"><span class="pre">cc_parent</span></code> points to the class
that defines the method (which may be a superclass of <code class="docutils literal notranslate"><span class="pre">type(self)</span></code>).
This is currently non-trivial to retrieve from a methods code.
In the future, this can be used to access the module state via
the defining class. See the rationale of <a class="pep reference internal" href="../pep-0573/" title="PEP 573 Module State Access from C Extension Methods">PEP 573</a> for details.</p>
<p>When the flag <code class="docutils literal notranslate"><span class="pre">CCALL_OBJCLASS</span></code> is set (as it will be for methods of
extension types), <code class="docutils literal notranslate"><span class="pre">cc_parent</span></code> is used for type checks like the following:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="nb">list</span><span class="o">.</span><span class="n">append</span><span class="p">({},</span> <span class="s2">&quot;x&quot;</span><span class="p">)</span>
<span class="gt">Traceback (most recent call last):</span>
File <span class="nb">&quot;&lt;stdin&gt;&quot;</span>, line <span class="m">1</span>, in <span class="n">&lt;module&gt;</span>
<span class="gr">TypeError</span>: <span class="n">descriptor &#39;append&#39; requires a &#39;list&#39; object but received a &#39;dict&#39;</span>
</pre></div>
</div>
<p>For functions of modules, <code class="docutils literal notranslate"><span class="pre">cc_parent</span></code> is set to the module.
Currently, this is exactly the same as <code class="docutils literal notranslate"><span class="pre">__self__</span></code>.
However, using <code class="docutils literal notranslate"><span class="pre">__self__</span></code> for the module is a quirk of the current implementation:
in the future, we want to allow functions which use <code class="docutils literal notranslate"><span class="pre">__self__</span></code>
in the normal way, for implementing methods.
Such functions can still use <code class="docutils literal notranslate"><span class="pre">cc_parent</span></code> instead to refer to the module.</p>
<p>The parent would also typically be used to implement <code class="docutils literal notranslate"><span class="pre">__qualname__</span></code>.
The new C API function <code class="docutils literal notranslate"><span class="pre">PyCCall_GenericGetQualname()</span></code> does exactly that.</p>
</section>
<section id="using-tp-print">
<h3><a class="toc-backref" href="#using-tp-print" role="doc-backlink">Using tp_print</a></h3>
<p>We propose to replace the existing unused field <code class="docutils literal notranslate"><span class="pre">tp_print</span></code>
by <code class="docutils literal notranslate"><span class="pre">tp_ccalloffset</span></code>.
Since <code class="docutils literal notranslate"><span class="pre">Py_TPFLAGS_HAVE_CCALL</span></code> would <em>not</em> be added to
<code class="docutils literal notranslate"><span class="pre">Py_TPFLAGS_DEFAULT</span></code>, this ensures full backwards compatibility for
existing extension modules setting <code class="docutils literal notranslate"><span class="pre">tp_print</span></code>.
It also means that we can require that <code class="docutils literal notranslate"><span class="pre">tp_ccalloffset</span></code> is a valid
offset when <code class="docutils literal notranslate"><span class="pre">Py_TPFLAGS_HAVE_CCALL</span></code> is specified:
we do not need to check <code class="docutils literal notranslate"><span class="pre">tp_ccalloffset</span> <span class="pre">!=</span> <span class="pre">0</span></code>.
In future Python versions, we may decide that <code class="docutils literal notranslate"><span class="pre">tp_print</span></code>
becomes <code class="docutils literal notranslate"><span class="pre">tp_ccalloffset</span></code> unconditionally,
drop the <code class="docutils literal notranslate"><span class="pre">Py_TPFLAGS_HAVE_CCALL</span></code> flag and instead check for
<code class="docutils literal notranslate"><span class="pre">tp_ccalloffset</span> <span class="pre">!=</span> <span class="pre">0</span></code>.</p>
<p><strong>NOTE</strong>: the exact layout of <code class="docutils literal notranslate"><span class="pre">PyTypeObject</span></code> is not part of the <a class="pep reference internal" href="../pep-0384/" title="PEP 384 Defining a Stable ABI">stable ABI</a>).
Therefore, changing the <code class="docutils literal notranslate"><span class="pre">tp_print</span></code> field from a <code class="docutils literal notranslate"><span class="pre">printfunc</span></code> (a function pointer)
to a <code class="docutils literal notranslate"><span class="pre">Py_ssize_t</span></code> should not be a problem,
even if this changes the memory layout of the <code class="docutils literal notranslate"><span class="pre">PyTypeObject</span></code> structure.
Moreover, on all systems for which binaries are commonly built
(Windows, Linux, macOS),
the size of <code class="docutils literal notranslate"><span class="pre">printfunc</span></code> and <code class="docutils literal notranslate"><span class="pre">Py_ssize_t</span></code> are the same,
so the issue of binary compatibility will not come up anyway.</p>
</section>
</section>
<section id="the-c-call-protocol">
<h2><a class="toc-backref" href="#the-c-call-protocol" role="doc-backlink">The C call protocol</a></h2>
<p>We say that a class implements the C call protocol
if it has the <code class="docutils literal notranslate"><span class="pre">Py_TPFLAGS_HAVE_CCALL</span></code> flag set
(as explained above, it must then set <code class="docutils literal notranslate"><span class="pre">tp_ccalloffset</span> <span class="pre">&gt;</span> <span class="pre">0</span></code>).
Such a class must implement <code class="docutils literal notranslate"><span class="pre">__call__</span></code> as described in this section
(in practice, this just means setting <code class="docutils literal notranslate"><span class="pre">tp_call</span></code> to <code class="docutils literal notranslate"><span class="pre">PyCCall_Call</span></code>).</p>
<p>The <code class="docutils literal notranslate"><span class="pre">cc_func</span></code> field is a C function pointer,
which plays the same role as the existing <code class="docutils literal notranslate"><span class="pre">ml_meth</span></code> field of <code class="docutils literal notranslate"><span class="pre">PyMethodDef</span></code>.
Its precise signature depends on flags.
The subset of flags influencing the signature of <code class="docutils literal notranslate"><span class="pre">cc_func</span></code>
is given by the bitmask <code class="docutils literal notranslate"><span class="pre">CCALL_SIGNATURE</span></code>.
Below are the possible values for <code class="docutils literal notranslate"><span class="pre">cc_flags</span> <span class="pre">&amp;</span> <span class="pre">CCALL_SIGNATURE</span></code>
together with the arguments that the C function takes.
The return value is always <code class="docutils literal notranslate"><span class="pre">PyObject</span> <span class="pre">*</span></code>.
The following are analogous to the existing <code class="docutils literal notranslate"><span class="pre">PyMethodDef</span></code>
signature flags:</p>
<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">CCALL_VARARGS</span></code>:
<code class="docutils literal notranslate"><span class="pre">cc_func(PyObject</span> <span class="pre">*self,</span> <span class="pre">PyObject</span> <span class="pre">*args)</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">CCALL_VARARGS</span> <span class="pre">|</span> <span class="pre">CCALL_KEYWORDS</span></code>:
<code class="docutils literal notranslate"><span class="pre">cc_func(PyObject</span> <span class="pre">*self,</span> <span class="pre">PyObject</span> <span class="pre">*args,</span> <span class="pre">PyObject</span> <span class="pre">*kwds)</span></code>
(<code class="docutils literal notranslate"><span class="pre">kwds</span></code> is either <code class="docutils literal notranslate"><span class="pre">NULL</span></code> or a dict; this dict must not be modified by the callee)</li>
<li><code class="docutils literal notranslate"><span class="pre">CCALL_FASTCALL</span></code>:
<code class="docutils literal notranslate"><span class="pre">cc_func(PyObject</span> <span class="pre">*self,</span> <span class="pre">PyObject</span> <span class="pre">*const</span> <span class="pre">*args,</span> <span class="pre">Py_ssize_t</span> <span class="pre">nargs)</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">CCALL_FASTCALL</span> <span class="pre">|</span> <span class="pre">CCALL_KEYWORDS</span></code>:
<code class="docutils literal notranslate"><span class="pre">cc_func(PyObject</span> <span class="pre">*self,</span> <span class="pre">PyObject</span> <span class="pre">*const</span> <span class="pre">*args,</span> <span class="pre">Py_ssize_t</span> <span class="pre">nargs,</span> <span class="pre">PyObject</span> <span class="pre">*kwnames)</span></code>
(<code class="docutils literal notranslate"><span class="pre">kwnames</span></code> is either <code class="docutils literal notranslate"><span class="pre">NULL</span></code> or a non-empty tuple of keyword names)</li>
<li><code class="docutils literal notranslate"><span class="pre">CCALL_NOARGS</span></code>:
<code class="docutils literal notranslate"><span class="pre">cc_func(PyObject</span> <span class="pre">*self,</span> <span class="pre">PyObject</span> <span class="pre">*unused)</span></code> (second argument is always <code class="docutils literal notranslate"><span class="pre">NULL</span></code>)</li>
<li><code class="docutils literal notranslate"><span class="pre">CCALL_O</span></code>:
<code class="docutils literal notranslate"><span class="pre">cc_func(PyObject</span> <span class="pre">*self,</span> <span class="pre">PyObject</span> <span class="pre">*arg)</span></code></li>
</ul>
<p>The flag <code class="docutils literal notranslate"><span class="pre">CCALL_DEFARG</span></code> may be combined with any of these.
If so, the C function takes an additional argument
as first argument before <code class="docutils literal notranslate"><span class="pre">self</span></code>,
namely a const pointer to the <code class="docutils literal notranslate"><span class="pre">PyCCallDef</span></code> structure used for this call.
For example, we have the following signature:</p>
<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">CCALL_DEFARG</span> <span class="pre">|</span> <span class="pre">CCALL_VARARGS</span></code>:
<code class="docutils literal notranslate"><span class="pre">cc_func(const</span> <span class="pre">PyCCallDef</span> <span class="pre">*def,</span> <span class="pre">PyObject</span> <span class="pre">*self,</span> <span class="pre">PyObject</span> <span class="pre">*args)</span></code></li>
</ul>
<p>One exception is <code class="docutils literal notranslate"><span class="pre">CCALL_DEFARG</span> <span class="pre">|</span> <span class="pre">CCALL_NOARGS</span></code>:
the <code class="docutils literal notranslate"><span class="pre">unused</span></code> argument is dropped, so the signature becomes</p>
<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">CCALL_DEFARG</span> <span class="pre">|</span> <span class="pre">CCALL_NOARGS</span></code>:
<code class="docutils literal notranslate"><span class="pre">cc_func(const</span> <span class="pre">PyCCallDef</span> <span class="pre">*def,</span> <span class="pre">PyObject</span> <span class="pre">*self)</span></code></li>
</ul>
<p><strong>NOTE</strong>: unlike the existing <code class="docutils literal notranslate"><span class="pre">METH_...</span></code> flags,
the <code class="docutils literal notranslate"><span class="pre">CCALL_...</span></code> constants do not necessarily represent single bits.
So checking <code class="docutils literal notranslate"><span class="pre">if</span> <span class="pre">(cc_flags</span> <span class="pre">&amp;</span> <span class="pre">CCALL_VARARGS)</span></code> is not a valid way
for checking the signature.
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 <code class="docutils literal notranslate"><span class="pre">cc_flags</span> <span class="pre">&amp;</span> <span class="pre">CCALL_SIGNATURE</span></code> form exactly the interval [0, …, 11].
This means that the compiler can easily
optimize a <code class="docutils literal notranslate"><span class="pre">switch</span></code> statement for those cases using a computed goto.</p>
<section id="checking-objclass">
<h3><a class="toc-backref" href="#checking-objclass" role="doc-backlink">Checking __objclass__</a></h3>
<p>If the <code class="docutils literal notranslate"><span class="pre">CCALL_OBJCLASS</span></code> flag is set and if <code class="docutils literal notranslate"><span class="pre">cr_self</span></code> is NULL
(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 <code class="docutils literal notranslate"><span class="pre">self</span></code>) must be an instance of
<code class="docutils literal notranslate"><span class="pre">cc_parent</span></code> (which must be a class).
If not, a <code class="docutils literal notranslate"><span class="pre">TypeError</span></code> is raised.</p>
</section>
<section id="self-slicing">
<h3><a class="toc-backref" href="#self-slicing" role="doc-backlink">Self slicing</a></h3>
<p>If <code class="docutils literal notranslate"><span class="pre">cr_self</span></code> is not NULL or if the flag <code class="docutils literal notranslate"><span class="pre">CCALL_SELFARG</span></code>
is not set in <code class="docutils literal notranslate"><span class="pre">cc_flags</span></code>, then the argument passed as <code class="docutils literal notranslate"><span class="pre">self</span></code>
is simply <code class="docutils literal notranslate"><span class="pre">cr_self</span></code>.</p>
<p>If <code class="docutils literal notranslate"><span class="pre">cr_self</span></code> is NULL and the flag <code class="docutils literal notranslate"><span class="pre">CCALL_SELFARG</span></code> is set,
then the first positional argument is removed from
<code class="docutils literal notranslate"><span class="pre">args</span></code> and instead passed as <code class="docutils literal notranslate"><span class="pre">self</span></code> argument to the C function.
Effectively, the first positional argument is treated as <code class="docutils literal notranslate"><span class="pre">__self__</span></code>.
If there are no positional arguments, <code class="docutils literal notranslate"><span class="pre">TypeError</span></code> is raised.</p>
<p>This process is called “self slicing” and a function is said to have self
slicing if <code class="docutils literal notranslate"><span class="pre">cr_self</span></code> is NULL and <code class="docutils literal notranslate"><span class="pre">CCALL_SELFARG</span></code> is set.</p>
<p>Note that a <code class="docutils literal notranslate"><span class="pre">CCALL_NOARGS</span></code> function with self slicing effectively has
one argument, namely <code class="docutils literal notranslate"><span class="pre">self</span></code>.
Analogously, a <code class="docutils literal notranslate"><span class="pre">CCALL_O</span></code> function with self slicing has two arguments.</p>
</section>
<section id="descriptor-behavior">
<h3><a class="toc-backref" href="#descriptor-behavior" role="doc-backlink">Descriptor behavior</a></h3>
<p>Classes supporting the C call protocol
must implement the descriptor protocol in a specific way.</p>
<p>This is required for an efficient implementation of bound methods:
if other code can make assumptions on what <code class="docutils literal notranslate"><span class="pre">__get__</span></code> does,
it enables optimizations which would not be possible otherwise.
In particular, we want to allow sharing
the <code class="docutils literal notranslate"><span class="pre">PyCCallDef</span></code> structure between bound and unbound methods.
We also need a correct implementation of <code class="docutils literal notranslate"><span class="pre">_PyObject_GetMethod</span></code>
which is used by the <code class="docutils literal notranslate"><span class="pre">LOAD_METHOD</span></code>/<code class="docutils literal notranslate"><span class="pre">CALL_METHOD</span></code> optimization.</p>
<p>First of all, if <code class="docutils literal notranslate"><span class="pre">func</span></code> supports the C call protocol,
then <code class="docutils literal notranslate"><span class="pre">func.__set__</span></code> and <code class="docutils literal notranslate"><span class="pre">func.__delete__</span></code> must not be implemented.</p>
<p>Second, <code class="docutils literal notranslate"><span class="pre">func.__get__</span></code> must behave as follows:</p>
<ul class="simple">
<li>If <code class="docutils literal notranslate"><span class="pre">cr_self</span></code> is not NULL, then <code class="docutils literal notranslate"><span class="pre">__get__</span></code> must be a no-op
in the sense that <code class="docutils literal notranslate"><span class="pre">func.__get__(obj,</span> <span class="pre">cls)(*args,</span> <span class="pre">**kwds)</span></code>
behaves exactly the same as <code class="docutils literal notranslate"><span class="pre">func(*args,</span> <span class="pre">**kwds)</span></code>.
It is also allowed for <code class="docutils literal notranslate"><span class="pre">__get__</span></code> to be not implemented at all.</li>
<li>If <code class="docutils literal notranslate"><span class="pre">cr_self</span></code> is NULL, then <code class="docutils literal notranslate"><span class="pre">func.__get__(obj,</span> <span class="pre">cls)(*args,</span> <span class="pre">**kwds)</span></code>
(with <code class="docutils literal notranslate"><span class="pre">obj</span></code> not None)
must be equivalent to <code class="docutils literal notranslate"><span class="pre">func(obj,</span> <span class="pre">*args,</span> <span class="pre">**kwds)</span></code>.
In particular, <code class="docutils literal notranslate"><span class="pre">__get__</span></code> must be implemented in this case.
This is unrelated to <a class="reference internal" href="#self-slicing">self slicing</a>: <code class="docutils literal notranslate"><span class="pre">obj</span></code> may be passed
as <code class="docutils literal notranslate"><span class="pre">self</span></code> argument to the C function or it may be the first positional argument.</li>
<li>If <code class="docutils literal notranslate"><span class="pre">cr_self</span></code> is NULL, then <code class="docutils literal notranslate"><span class="pre">func.__get__(None,</span> <span class="pre">cls)(*args,</span> <span class="pre">**kwds)</span></code>
must be equivalent to <code class="docutils literal notranslate"><span class="pre">func(*args,</span> <span class="pre">**kwds)</span></code>.</li>
</ul>
<p>There are no restrictions on the object <code class="docutils literal notranslate"><span class="pre">func.__get__(obj,</span> <span class="pre">cls)</span></code>.
The latter is not required to implement the C call protocol for example.
We only specify what <code class="docutils literal notranslate"><span class="pre">func.__get__(obj,</span> <span class="pre">cls).__call__</span></code> does.</p>
<p>For classes that do not care about <code class="docutils literal notranslate"><span class="pre">__self__</span></code> and <code class="docutils literal notranslate"><span class="pre">__get__</span></code> at all,
the easiest solution is to assign <code class="docutils literal notranslate"><span class="pre">cr_self</span> <span class="pre">=</span> <span class="pre">Py_None</span></code>
(or any other non-NULL value).</p>
</section>
<section id="the-name-attribute">
<h3><a class="toc-backref" href="#the-name-attribute" role="doc-backlink">The __name__ attribute</a></h3>
<p>The C call protocol requires that the function has a <code class="docutils literal notranslate"><span class="pre">__name__</span></code>
attribute which is of type <code class="docutils literal notranslate"><span class="pre">str</span></code> (not a subclass).</p>
<p>Furthermore, the object returned by <code class="docutils literal notranslate"><span class="pre">__name__</span></code> must be stored somewhere;
it cannot be a temporary object.
This is required because <code class="docutils literal notranslate"><span class="pre">PyEval_GetFuncName</span></code>
uses a borrowed reference to the <code class="docutils literal notranslate"><span class="pre">__name__</span></code> attribute
(see also <a class="footnote-reference brackets" href="#badcapi" id="id1">[2]</a>).</p>
</section>
<section id="generic-api-functions">
<h3><a class="toc-backref" href="#generic-api-functions" role="doc-backlink">Generic API functions</a></h3>
<p>This section lists the new public API functions or macros
dealing with the C call protocol.</p>
<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">int</span> <span class="pre">PyCCall_Check(PyObject</span> <span class="pre">*op)</span></code>:
return true if <code class="docutils literal notranslate"><span class="pre">op</span></code> implements the C call protocol.</li>
</ul>
<p>All the functions and macros below
apply to any instance supporting the C call protocol.
In other words, <code class="docutils literal notranslate"><span class="pre">PyCCall_Check(func)</span></code> must be true.</p>
<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">PyObject</span> <span class="pre">*PyCCall_Call(PyObject</span> <span class="pre">*func,</span> <span class="pre">PyObject</span> <span class="pre">*args,</span> <span class="pre">PyObject</span> <span class="pre">*kwds)</span></code>:
call <code class="docutils literal notranslate"><span class="pre">func</span></code> with positional arguments <code class="docutils literal notranslate"><span class="pre">args</span></code>
and keyword arguments <code class="docutils literal notranslate"><span class="pre">kwds</span></code> (<code class="docutils literal notranslate"><span class="pre">kwds</span></code> may be NULL).
This function is meant to be put in the <code class="docutils literal notranslate"><span class="pre">tp_call</span></code> slot.</li>
<li><code class="docutils literal notranslate"><span class="pre">PyObject</span> <span class="pre">*PyCCall_FastCall(PyObject</span> <span class="pre">*func,</span> <span class="pre">PyObject</span> <span class="pre">*const</span> <span class="pre">*args,</span> <span class="pre">Py_ssize_t</span> <span class="pre">nargs,</span> <span class="pre">PyObject</span> <span class="pre">*kwds)</span></code>:
call <code class="docutils literal notranslate"><span class="pre">func</span></code> with <code class="docutils literal notranslate"><span class="pre">nargs</span></code> positional arguments given by <code class="docutils literal notranslate"><span class="pre">args[0]</span></code>, …, <code class="docutils literal notranslate"><span class="pre">args[nargs-1]</span></code>.
The parameter <code class="docutils literal notranslate"><span class="pre">kwds</span></code> can be NULL (no keyword arguments),
a dict with <code class="docutils literal notranslate"><span class="pre">name:value</span></code> items or a tuple with keyword names.
In the latter case, the keyword values are stored in the <code class="docutils literal notranslate"><span class="pre">args</span></code>
array, starting at <code class="docutils literal notranslate"><span class="pre">args[nargs]</span></code>.</li>
</ul>
<p>Macros to access the <code class="docutils literal notranslate"><span class="pre">PyCCallRoot</span></code> and <code class="docutils literal notranslate"><span class="pre">PyCCallDef</span></code> structures:</p>
<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">const</span> <span class="pre">PyCCallRoot</span> <span class="pre">*PyCCall_CCALLROOT(PyObject</span> <span class="pre">*func)</span></code>:
pointer to the <code class="docutils literal notranslate"><span class="pre">PyCCallRoot</span></code> structure inside <code class="docutils literal notranslate"><span class="pre">func</span></code>.</li>
<li><code class="docutils literal notranslate"><span class="pre">const</span> <span class="pre">PyCCallDef</span> <span class="pre">*PyCCall_CCALLDEF(PyObject</span> <span class="pre">*func)</span></code>:
shorthand for <code class="docutils literal notranslate"><span class="pre">PyCCall_CCALLROOT(func)-&gt;cr_ccall</span></code>.</li>
<li><code class="docutils literal notranslate"><span class="pre">uint32_t</span> <span class="pre">PyCCall_FLAGS(PyObject</span> <span class="pre">*func)</span></code>:
shorthand for <code class="docutils literal notranslate"><span class="pre">PyCCall_CCALLROOT(func)-&gt;cr_ccall-&gt;cc_flags</span></code>.</li>
<li><code class="docutils literal notranslate"><span class="pre">PyObject</span> <span class="pre">*PyCCall_SELF(PyOject</span> <span class="pre">*func)</span></code>:
shorthand for <code class="docutils literal notranslate"><span class="pre">PyCCall_CCALLROOT(func)-&gt;cr_self</span></code>.</li>
</ul>
<p>Generic getters, meant to be put into the <code class="docutils literal notranslate"><span class="pre">tp_getset</span></code> array:</p>
<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">PyObject</span> <span class="pre">*PyCCall_GenericGetParent(PyObject</span> <span class="pre">*func,</span> <span class="pre">void</span> <span class="pre">*closure)</span></code>:
return <code class="docutils literal notranslate"><span class="pre">cc_parent</span></code>.
Raise <code class="docutils literal notranslate"><span class="pre">AttributeError</span></code> if <code class="docutils literal notranslate"><span class="pre">cc_parent</span></code> is NULL.</li>
<li><code class="docutils literal notranslate"><span class="pre">PyObject</span> <span class="pre">*PyCCall_GenericGetQualname(PyObject</span> <span class="pre">*func,</span> <span class="pre">void</span> <span class="pre">*closure)</span></code>:
return a string suitable for using as <code class="docutils literal notranslate"><span class="pre">__qualname__</span></code>.
This uses the <code class="docutils literal notranslate"><span class="pre">__qualname__</span></code> of <code class="docutils literal notranslate"><span class="pre">cc_parent</span></code> if possible.
It also uses the <code class="docutils literal notranslate"><span class="pre">__name__</span></code> attribute.</li>
</ul>
</section>
<section id="profiling">
<h3><a class="toc-backref" href="#profiling" role="doc-backlink">Profiling</a></h3>
<p>The profiling events
<code class="docutils literal notranslate"><span class="pre">c_call</span></code>, <code class="docutils literal notranslate"><span class="pre">c_return</span></code> and <code class="docutils literal notranslate"><span class="pre">c_exception</span></code> are only generated
when calling actual instances of <code class="docutils literal notranslate"><span class="pre">builtin_function_or_method</span></code> or <code class="docutils literal notranslate"><span class="pre">method_descriptor</span></code>.
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.</p>
</section>
</section>
<section id="changes-to-built-in-functions-and-methods">
<h2><a class="toc-backref" href="#changes-to-built-in-functions-and-methods" role="doc-backlink">Changes to built-in functions and methods</a></h2>
<p>The reference implementation of this PEP changes
the existing classes <code class="docutils literal notranslate"><span class="pre">builtin_function_or_method</span></code> and <code class="docutils literal notranslate"><span class="pre">method_descriptor</span></code>
to use the C call protocol.
In fact, those two classes are almost merged:
the implementation becomes very similar, but they remain separate classes
(mostly for backwards compatibility).
The <code class="docutils literal notranslate"><span class="pre">PyCCallDef</span></code> structure is simply stored
as part of the object structure.
Both classes use <code class="docutils literal notranslate"><span class="pre">PyCFunctionObject</span></code> as object structure.
This is the new layout for both classes:</p>
<div class="highlight-default notranslate" id="pycfunctionobject"><div class="highlight"><pre><span></span><span class="n">typedef</span> <span class="n">struct</span> <span class="p">{</span>
<span class="n">PyObject_HEAD</span>
<span class="n">PyCCallDef</span> <span class="o">*</span><span class="n">m_ccall</span><span class="p">;</span>
<span class="n">PyObject</span> <span class="o">*</span><span class="n">m_self</span><span class="p">;</span> <span class="o">/*</span> <span class="n">Passed</span> <span class="k">as</span> <span class="s1">&#39;self&#39;</span> <span class="n">arg</span> <span class="n">to</span> <span class="n">the</span> <span class="n">C</span> <span class="n">function</span> <span class="o">*/</span>
<span class="n">PyCCallDef</span> <span class="n">_ccalldef</span><span class="p">;</span> <span class="o">/*</span> <span class="n">Storage</span> <span class="k">for</span> <span class="n">m_ccall</span> <span class="o">*/</span>
<span class="n">PyObject</span> <span class="o">*</span><span class="n">m_name</span><span class="p">;</span> <span class="o">/*</span> <span class="vm">__name__</span><span class="p">;</span> <span class="nb">str</span> <span class="nb">object</span> <span class="p">(</span><span class="ow">not</span> <span class="n">NULL</span><span class="p">)</span> <span class="o">*/</span>
<span class="n">PyObject</span> <span class="o">*</span><span class="n">m_module</span><span class="p">;</span> <span class="o">/*</span> <span class="vm">__module__</span><span class="p">;</span> <span class="n">can</span> <span class="n">be</span> <span class="n">anything</span> <span class="o">*/</span>
<span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">m_doc</span><span class="p">;</span> <span class="o">/*</span> <span class="n">__text_signature__</span> <span class="ow">and</span> <span class="vm">__doc__</span> <span class="o">*/</span>
<span class="n">PyObject</span> <span class="o">*</span><span class="n">m_weakreflist</span><span class="p">;</span> <span class="o">/*</span> <span class="n">List</span> <span class="n">of</span> <span class="n">weak</span> <span class="n">references</span> <span class="o">*/</span>
<span class="p">}</span> <span class="n">PyCFunctionObject</span><span class="p">;</span>
</pre></div>
</div>
<p>For functions of a module and for unbound methods of extension types,
<code class="docutils literal notranslate"><span class="pre">m_ccall</span></code> points to the <code class="docutils literal notranslate"><span class="pre">_ccalldef</span></code> field.
For bound methods, <code class="docutils literal notranslate"><span class="pre">m_ccall</span></code> points to the <code class="docutils literal notranslate"><span class="pre">PyCCallDef</span></code>
of the unbound method.</p>
<p><strong>NOTE</strong>: the new layout of <code class="docutils literal notranslate"><span class="pre">method_descriptor</span></code> changes it
such that it no longer starts with <code class="docutils literal notranslate"><span class="pre">PyDescr_COMMON</span></code>.
This is purely an implementation detail and it should cause few (if any)
compatibility problems.</p>
<section id="c-api-functions">
<h3><a class="toc-backref" href="#c-api-functions" role="doc-backlink">C API functions</a></h3>
<p>The following function is added (also to the <a class="pep reference internal" href="../pep-0384/" title="PEP 384 Defining a Stable ABI">stable ABI</a>):</p>
<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">PyObject</span> <span class="pre">*</span> <span class="pre">PyCFunction_ClsNew(PyTypeObject</span> <span class="pre">*cls,</span> <span class="pre">PyMethodDef</span> <span class="pre">*ml,</span> <span class="pre">PyObject</span> <span class="pre">*self,</span> <span class="pre">PyObject</span> <span class="pre">*module,</span> <span class="pre">PyObject</span> <span class="pre">*parent)</span></code>:
create a new object with object structure <code class="docutils literal notranslate"><span class="pre">PyCFunctionObject</span></code> and class <code class="docutils literal notranslate"><span class="pre">cls</span></code>.
The entries of the <code class="docutils literal notranslate"><span class="pre">PyMethodDef</span></code> structure are used to construct
the new object, but the pointer to the <code class="docutils literal notranslate"><span class="pre">PyMethodDef</span></code> structure
is not stored.
The flags for the C call protocol are automatically determined in terms
of <code class="docutils literal notranslate"><span class="pre">ml-&gt;ml_flags</span></code>, <code class="docutils literal notranslate"><span class="pre">self</span></code> and <code class="docutils literal notranslate"><span class="pre">parent</span></code>.</li>
</ul>
<p>The existing functions <code class="docutils literal notranslate"><span class="pre">PyCFunction_New</span></code>, <code class="docutils literal notranslate"><span class="pre">PyCFunction_NewEx</span></code> and
<code class="docutils literal notranslate"><span class="pre">PyDescr_NewMethod</span></code> are implemented in terms of <code class="docutils literal notranslate"><span class="pre">PyCFunction_ClsNew</span></code>.</p>
<p>The undocumented functions <code class="docutils literal notranslate"><span class="pre">PyCFunction_GetFlags</span></code>
and <code class="docutils literal notranslate"><span class="pre">PyCFunction_GET_FLAGS</span></code> are deprecated.
They are still artificially supported by storing the original <code class="docutils literal notranslate"><span class="pre">METH_...</span></code>
flags in a bitfield inside <code class="docutils literal notranslate"><span class="pre">cc_flags</span></code>.
Despite the fact that <code class="docutils literal notranslate"><span class="pre">PyCFunction_GetFlags</span></code> is technically
part of the <a class="pep reference internal" href="../pep-0384/" title="PEP 384 Defining a Stable ABI">stable ABI</a>,
it is highly unlikely to be used that way:
first of all, it is not even documented.
Second, the flag <code class="docutils literal notranslate"><span class="pre">METH_FASTCALL</span></code>
is not part of the stable ABI but it is very common
(because of Argument Clinic).
So, if one cannot support <code class="docutils literal notranslate"><span class="pre">METH_FASTCALL</span></code>,
it is hard to imagine a use case for <code class="docutils literal notranslate"><span class="pre">PyCFunction_GetFlags</span></code>.
The fact that <code class="docutils literal notranslate"><span class="pre">PyCFunction_GET_FLAGS</span></code> and <code class="docutils literal notranslate"><span class="pre">PyCFunction_GetFlags</span></code>
are not used at all by CPython outside of <code class="docutils literal notranslate"><span class="pre">Objects/call.c</span></code>
further shows that these functions are not particularly useful.</p>
</section>
</section>
<section id="inheritance">
<h2><a class="toc-backref" href="#inheritance" role="doc-backlink">Inheritance</a></h2>
<p>Extension types inherit the type flag <code class="docutils literal notranslate"><span class="pre">Py_TPFLAGS_HAVE_CCALL</span></code>
and the value <code class="docutils literal notranslate"><span class="pre">tp_ccalloffset</span></code> from the base class,
provided that they implement <code class="docutils literal notranslate"><span class="pre">tp_call</span></code> and <code class="docutils literal notranslate"><span class="pre">tp_descr_get</span></code>
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).</p>
</section>
<section id="performance">
<h2><a class="toc-backref" href="#performance" role="doc-backlink">Performance</a></h2>
<p>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.</p>
<p>Here are a few pointers to the <code class="docutils literal notranslate"><span class="pre">python-dev</span></code> mailing list where
performance improvements are discussed:</p>
<ul class="simple">
<li><a class="reference external" href="https://mail.python.org/pipermail/python-dev/2018-July/154571.html">https://mail.python.org/pipermail/python-dev/2018-July/154571.html</a></li>
<li><a class="reference external" href="https://mail.python.org/pipermail/python-dev/2018-July/154740.html">https://mail.python.org/pipermail/python-dev/2018-July/154740.html</a></li>
<li><a class="reference external" href="https://mail.python.org/pipermail/python-dev/2018-July/154775.html">https://mail.python.org/pipermail/python-dev/2018-July/154775.html</a></li>
<li><a class="reference external" href="https://mail.python.org/pipermail/python-dev/2019-April/156954.html">https://mail.python.org/pipermail/python-dev/2019-April/156954.html</a></li>
</ul>
</section>
<section id="stable-abi">
<h2><a class="toc-backref" href="#stable-abi" role="doc-backlink">Stable ABI</a></h2>
<p>The function <code class="docutils literal notranslate"><span class="pre">PyCFunction_ClsNew</span></code> is added to the <a class="pep reference internal" href="../pep-0384/" title="PEP 384 Defining a Stable ABI">stable ABI</a>.</p>
<p>None of the functions, structures or constants dealing with the C call protocol
are added to the stable ABI.</p>
<p>There are two reasons for this:
first of all, the most useful feature of the C call protocol is probably the
<code class="docutils literal notranslate"><span class="pre">METH_FASTCALL</span></code> calling convention.
Given that this is not even part of the public API (see also <a class="pep reference internal" href="../pep-0579/" title="PEP 579 Refactoring C functions and methods">PEP 579</a>, issue 6),
it would be strange to add anything else from the C call protocol
to the stable ABI.</p>
<p>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.</p>
</section>
<section id="backwards-compatibility">
<h2><a class="toc-backref" href="#backwards-compatibility" role="doc-backlink">Backwards compatibility</a></h2>
<p>There is no difference at all for the Python interface,
nor for the documented C API
(in the sense that all functions remain supported with the same functionality).</p>
<p>The only potential breakage is with C code
which accesses the internals of <code class="docutils literal notranslate"><span class="pre">PyCFunctionObject</span></code> and <code class="docutils literal notranslate"><span class="pre">PyMethodDescrObject</span></code>.
We expect very few problems because of this.</p>
</section>
<section id="rationale">
<h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2>
<section id="why-is-this-better-than-pep-575">
<h3><a class="toc-backref" href="#why-is-this-better-than-pep-575" role="doc-backlink">Why is this better than PEP 575?</a></h3>
<p>One of the major complaints of <a class="pep reference internal" href="../pep-0575/" title="PEP 575 Unifying function/method classes">PEP 575</a> was that is was coupling
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 <code class="docutils literal notranslate"><span class="pre">base_function</span></code>.
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.
For example, <code class="docutils literal notranslate"><span class="pre">functools.lru_cache</span></code> cannot implement <a class="pep reference internal" href="../pep-0575/" title="PEP 575 Unifying function/method classes">PEP 575</a> as-is.</p>
<p>It also complicated the implementation precisely because changes
were needed both in the implementation details and in the class hierarchy.</p>
<p>The current PEP does not have these problems.</p>
</section>
<section id="why-store-the-function-pointer-in-the-instance">
<h3><a class="toc-backref" href="#why-store-the-function-pointer-in-the-instance" role="doc-backlink">Why store the function pointer in the instance?</a></h3>
<p>The actual information needed for calling an object
is stored in the instance (in the <code class="docutils literal notranslate"><span class="pre">PyCCallDef</span></code> structure)
instead of the class.
This is different from the <code class="docutils literal notranslate"><span class="pre">tp_call</span></code> slot or earlier attempts
at implementing a <code class="docutils literal notranslate"><span class="pre">tp_fastcall</span></code> slot <a class="footnote-reference brackets" href="#bpo29259" id="id2">[1]</a>.</p>
<p>The main use case is built-in functions and methods.
For those, the C function to be called does depend on the instance.</p>
<p>Note that the current protocol makes it easy to support the case
where the same C function is called for all instances:
just use a single static <code class="docutils literal notranslate"><span class="pre">PyCCallDef</span></code> structure for every instance.</p>
</section>
<section id="why-ccall-objclass">
<h3><a class="toc-backref" href="#why-ccall-objclass" role="doc-backlink">Why CCALL_OBJCLASS?</a></h3>
<p>The flag <code class="docutils literal notranslate"><span class="pre">CCALL_OBJCLASS</span></code> is meant to support various cases
where the class of a <code class="docutils literal notranslate"><span class="pre">self</span></code> argument must be checked, such as:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="nb">list</span><span class="o">.</span><span class="n">append</span><span class="p">({},</span> <span class="kc">None</span><span class="p">)</span>
<span class="gt">Traceback (most recent call last):</span>
File <span class="nb">&quot;&lt;stdin&gt;&quot;</span>, line <span class="m">1</span>, in <span class="n">&lt;module&gt;</span>
<span class="gr">TypeError</span>: <span class="n">append() requires a &#39;list&#39; object but received a &#39;dict&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">list</span><span class="o">.</span><span class="fm">__len__</span><span class="p">({})</span>
<span class="gt">Traceback (most recent call last):</span>
File <span class="nb">&quot;&lt;stdin&gt;&quot;</span>, line <span class="m">1</span>, in <span class="n">&lt;module&gt;</span>
<span class="gr">TypeError</span>: <span class="n">descriptor &#39;__len__&#39; requires a &#39;list&#39; object but received a &#39;dict&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">float</span><span class="o">.</span><span class="vm">__dict__</span><span class="p">[</span><span class="s2">&quot;fromhex&quot;</span><span class="p">](</span><span class="nb">list</span><span class="p">,</span> <span class="s2">&quot;0xff&quot;</span><span class="p">)</span>
<span class="gt">Traceback (most recent call last):</span>
File <span class="nb">&quot;&lt;stdin&gt;&quot;</span>, line <span class="m">1</span>, in <span class="n">&lt;module&gt;</span>
<span class="gr">TypeError</span>: <span class="n">descriptor &#39;fromhex&#39; for type &#39;float&#39; doesn&#39;t apply to type &#39;list&#39;</span>
</pre></div>
</div>
<p>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.</p>
</section>
<section id="why-ccall-selfarg">
<h3><a class="toc-backref" href="#why-ccall-selfarg" role="doc-backlink">Why CCALL_SELFARG?</a></h3>
<p>The flag <code class="docutils literal notranslate"><span class="pre">CCALL_SELFARG</span></code> and the concept of self slicing
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 <code class="docutils literal notranslate"><span class="pre">self</span></code> argument
and this is simply the first positional argument of an unbound method call.</p>
<p>For example, <code class="docutils literal notranslate"><span class="pre">list.append</span></code> is a <code class="docutils literal notranslate"><span class="pre">METH_O</span></code> method.
Both the calls <code class="docutils literal notranslate"><span class="pre">list.append([],</span> <span class="pre">42)</span></code> and <code class="docutils literal notranslate"><span class="pre">[].append(42)</span></code> should
translate to the C call <code class="docutils literal notranslate"><span class="pre">list_append([],</span> <span class="pre">42)</span></code>.</p>
<p>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 <code class="docutils literal notranslate"><span class="pre">PyCCallDef</span></code>
structure (with the <code class="docutils literal notranslate"><span class="pre">CCALL_SELFARG</span></code> flag set).</p>
<p>So, <code class="docutils literal notranslate"><span class="pre">CCALL_SELFARG</span></code> has two advantages:
there is no extra layer of indirection for calling methods
and constructing bound methods does not require setting up a <code class="docutils literal notranslate"><span class="pre">PyCCallDef</span></code> structure.</p>
<p>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
a method takes 1 or 2 arguments:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="k">class</span> <span class="nc">List</span><span class="p">(</span><span class="nb">list</span><span class="p">):</span>
<span class="gp">... </span> <span class="k">def</span> <span class="nf">myappend</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">item</span><span class="p">):</span>
<span class="gp">... </span> <span class="bp">self</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">List</span><span class="p">()</span><span class="o">.</span><span class="n">myappend</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
<span class="gt">Traceback (most recent call last):</span>
File <span class="nb">&quot;&lt;stdin&gt;&quot;</span>, line <span class="m">1</span>, in <span class="n">&lt;module&gt;</span>
<span class="gr">TypeError</span>: <span class="n">myappend() takes 2 positional arguments but 3 were given</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">List</span><span class="p">()</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
<span class="gt">Traceback (most recent call last):</span>
File <span class="nb">&quot;&lt;stdin&gt;&quot;</span>, line <span class="m">1</span>, in <span class="n">&lt;module&gt;</span>
<span class="gr">TypeError</span>: <span class="n">append() takes exactly one argument (2 given)</span>
</pre></div>
</div>
<p>It is currently impossible for <code class="docutils literal notranslate"><span class="pre">PyCFunction_Call</span></code>
to know the actual number of user-visible arguments
since it cannot distinguish at runtime between
a function (without <code class="docutils literal notranslate"><span class="pre">self</span></code> argument) and a bound method (with <code class="docutils literal notranslate"><span class="pre">self</span></code> argument).
The <code class="docutils literal notranslate"><span class="pre">CCALL_SELFARG</span></code> flag makes this difference explicit.</p>
</section>
<section id="why-ccall-defarg">
<h3><a class="toc-backref" href="#why-ccall-defarg" role="doc-backlink">Why CCALL_DEFARG?</a></h3>
<p>The flag <code class="docutils literal notranslate"><span class="pre">CCALL_DEFARG</span></code> gives the callee access to the <code class="docutils literal notranslate"><span class="pre">PyCCallDef</span> <span class="pre">*</span></code>.
There are various use cases for this:</p>
<ol class="arabic simple">
<li>The callee can use the <code class="docutils literal notranslate"><span class="pre">cc_parent</span></code> field, which is useful for <a class="pep reference internal" href="../pep-0573/" title="PEP 573 Module State Access from C Extension Methods">PEP 573</a>.</li>
<li>Applications are free to extend the <code class="docutils literal notranslate"><span class="pre">PyCCallDef</span></code> structure with user-defined
fields, which can then be accessed analogously.</li>
<li>In the case where the <code class="docutils literal notranslate"><span class="pre">PyCCallDef</span></code> structure
is part of the object structure
(this is true for example for <a class="reference internal" href="#pycfunctionobject">PyCFunctionObject</a>),
an appropriate offset can be subtracted from the <code class="docutils literal notranslate"><span class="pre">PyCCallDef</span></code> pointer
to get a pointer to the callable object defining that <code class="docutils literal notranslate"><span class="pre">PyCCallDef</span></code>.</li>
</ol>
<p>An earlier version of this PEP defined a flag <code class="docutils literal notranslate"><span class="pre">CCALL_FUNCARG</span></code>
instead of <code class="docutils literal notranslate"><span class="pre">CCALL_DEFARG</span></code> 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 <code class="docutils literal notranslate"><span class="pre">PyCCallDef</span> <span class="pre">*</span></code> instead, this ambiguity is gone
since the bound method uses the <code class="docutils literal notranslate"><span class="pre">PyCCallDef</span> <span class="pre">*</span></code> from the wrapped function.</p>
</section>
<section id="replacing-tp-print">
<h3><a class="toc-backref" href="#replacing-tp-print" role="doc-backlink">Replacing tp_print</a></h3>
<p>We repurpose <code class="docutils literal notranslate"><span class="pre">tp_print</span></code> as <code class="docutils literal notranslate"><span class="pre">tp_ccalloffset</span></code> because this makes
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 <a class="reference external" href="https://mail.python.org/pipermail/python-dev/2018-June/153927.html">https://mail.python.org/pipermail/python-dev/2018-June/153927.html</a>).</p>
</section>
</section>
<section id="alternative-suggestions">
<h2><a class="toc-backref" href="#alternative-suggestions" role="doc-backlink">Alternative suggestions</a></h2>
<p><a class="pep reference internal" href="../pep-0576/" title="PEP 576 Rationalize Built-in function classes">PEP 576</a> is an alternative approach to solving the same problem as this PEP.
See <a class="reference external" href="https://mail.python.org/pipermail/python-dev/2018-July/154238.html">https://mail.python.org/pipermail/python-dev/2018-July/154238.html</a>
for comments on the difference between <a class="pep reference internal" href="../pep-0576/" title="PEP 576 Rationalize Built-in function classes">PEP 576</a> and <a class="pep reference internal" href="../pep-0580/" title="PEP 580 The C call protocol">PEP 580</a>.</p>
</section>
<section id="discussion">
<h2><a class="toc-backref" href="#discussion" role="doc-backlink">Discussion</a></h2>
<p>Links to threads on the <code class="docutils literal notranslate"><span class="pre">python-dev</span></code> mailing list
where this PEP has been discussed:</p>
<ul class="simple">
<li><a class="reference external" href="https://mail.python.org/pipermail/python-dev/2018-June/153938.html">https://mail.python.org/pipermail/python-dev/2018-June/153938.html</a></li>
<li><a class="reference external" href="https://mail.python.org/pipermail/python-dev/2018-June/153984.html">https://mail.python.org/pipermail/python-dev/2018-June/153984.html</a></li>
<li><a class="reference external" href="https://mail.python.org/pipermail/python-dev/2018-July/154238.html">https://mail.python.org/pipermail/python-dev/2018-July/154238.html</a></li>
<li><a class="reference external" href="https://mail.python.org/pipermail/python-dev/2018-July/154470.html">https://mail.python.org/pipermail/python-dev/2018-July/154470.html</a></li>
<li><a class="reference external" href="https://mail.python.org/pipermail/python-dev/2018-July/154571.html">https://mail.python.org/pipermail/python-dev/2018-July/154571.html</a></li>
<li><a class="reference external" href="https://mail.python.org/pipermail/python-dev/2018-September/155166.html">https://mail.python.org/pipermail/python-dev/2018-September/155166.html</a></li>
<li><a class="reference external" href="https://mail.python.org/pipermail/python-dev/2018-October/155403.html">https://mail.python.org/pipermail/python-dev/2018-October/155403.html</a></li>
<li><a class="reference external" href="https://mail.python.org/pipermail/python-dev/2019-March/156853.html">https://mail.python.org/pipermail/python-dev/2019-March/156853.html</a></li>
<li><a class="reference external" href="https://mail.python.org/pipermail/python-dev/2019-March/156879.html">https://mail.python.org/pipermail/python-dev/2019-March/156879.html</a></li>
</ul>
</section>
<section id="reference-implementation">
<h2><a class="toc-backref" href="#reference-implementation" role="doc-backlink">Reference implementation</a></h2>
<p>The reference implementation can be found at
<a class="reference external" href="https://github.com/jdemeyer/cpython/tree/pep580">https://github.com/jdemeyer/cpython/tree/pep580</a></p>
<p>For an example of using the C call protocol,
the following branch implements <code class="docutils literal notranslate"><span class="pre">functools.lru_cache</span></code> using <a class="pep reference internal" href="../pep-0580/" title="PEP 580 The C call protocol">PEP 580</a>:
<a class="reference external" href="https://github.com/jdemeyer/cpython/tree/lru580">https://github.com/jdemeyer/cpython/tree/lru580</a></p>
</section>
<section id="references">
<h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2>
<aside class="footnote-list brackets">
<aside class="footnote brackets" id="bpo29259" role="doc-footnote">
<dt class="label" id="bpo29259">[<a href="#id2">1</a>]</dt>
<dd>Add tp_fastcall to PyTypeObject: support FASTCALL calling convention for all callable objects,
<a class="reference external" href="https://bugs.python.org/issue29259">https://bugs.python.org/issue29259</a></aside>
<aside class="footnote brackets" id="badcapi" role="doc-footnote">
<dt class="label" id="badcapi">[<a href="#id1">2</a>]</dt>
<dd>Bad C API,
<a class="reference external" href="https://pythoncapi.readthedocs.io/bad_api.html#bad-c-api">https://pythoncapi.readthedocs.io/bad_api.html#bad-c-api</a></aside>
</aside>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document has been placed in the public domain.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0580.rst">https://github.com/python/peps/blob/main/peps/pep-0580.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0580.rst">2023-09-09 17:39:29 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#rejection-notice">Rejection Notice</a></li>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#motivation">Motivation</a></li>
<li><a class="reference internal" href="#overview">Overview</a></li>
<li><a class="reference internal" href="#new-data-structures">New data structures</a><ul>
<li><a class="reference internal" href="#parent">Parent</a></li>
<li><a class="reference internal" href="#using-tp-print">Using tp_print</a></li>
</ul>
</li>
<li><a class="reference internal" href="#the-c-call-protocol">The C call protocol</a><ul>
<li><a class="reference internal" href="#checking-objclass">Checking __objclass__</a></li>
<li><a class="reference internal" href="#self-slicing">Self slicing</a></li>
<li><a class="reference internal" href="#descriptor-behavior">Descriptor behavior</a></li>
<li><a class="reference internal" href="#the-name-attribute">The __name__ attribute</a></li>
<li><a class="reference internal" href="#generic-api-functions">Generic API functions</a></li>
<li><a class="reference internal" href="#profiling">Profiling</a></li>
</ul>
</li>
<li><a class="reference internal" href="#changes-to-built-in-functions-and-methods">Changes to built-in functions and methods</a><ul>
<li><a class="reference internal" href="#c-api-functions">C API functions</a></li>
</ul>
</li>
<li><a class="reference internal" href="#inheritance">Inheritance</a></li>
<li><a class="reference internal" href="#performance">Performance</a></li>
<li><a class="reference internal" href="#stable-abi">Stable ABI</a></li>
<li><a class="reference internal" href="#backwards-compatibility">Backwards compatibility</a></li>
<li><a class="reference internal" href="#rationale">Rationale</a><ul>
<li><a class="reference internal" href="#why-is-this-better-than-pep-575">Why is this better than PEP 575?</a></li>
<li><a class="reference internal" href="#why-store-the-function-pointer-in-the-instance">Why store the function pointer in the instance?</a></li>
<li><a class="reference internal" href="#why-ccall-objclass">Why CCALL_OBJCLASS?</a></li>
<li><a class="reference internal" href="#why-ccall-selfarg">Why CCALL_SELFARG?</a></li>
<li><a class="reference internal" href="#why-ccall-defarg">Why CCALL_DEFARG?</a></li>
<li><a class="reference internal" href="#replacing-tp-print">Replacing tp_print</a></li>
</ul>
</li>
<li><a class="reference internal" href="#alternative-suggestions">Alternative suggestions</a></li>
<li><a class="reference internal" href="#discussion">Discussion</a></li>
<li><a class="reference internal" href="#reference-implementation">Reference implementation</a></li>
<li><a class="reference internal" href="#references">References</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0580.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>