Skip to main content

ABI and calling conventions

This page describes the calling conventions the interpreter uses internally. Implementing a Python runtime requires reproducing these exactly: a built-in function declared with METH_FASTCALL must be called with the fastcall shape, never the tuple/dict shape.

Source-of-record: Include/cpython/methodobject.h, Include/cpython/abstract.h, Objects/call.c, Objects/methodobject.c.

Method calling-convention flags

A PyMethodDef declares a built-in function. The ml_flags field chooses the calling convention.

FlagArgument shape
METH_VARARGS(self, args_tuple).
`METH_VARARGSMETH_KEYWORDS`
METH_FASTCALL(self, args_array, nargs).
`METH_FASTCALLMETH_KEYWORDS`
METH_NOARGS(self, NULL). Args ignored.
METH_O(self, arg). Single positional.
METH_CLASSMarker: function is a class method.
METH_STATICMarker: function is a static method.
METH_COEXISTAllow coexistence with a slot of the same name.
METH_METHODThe fastcall variant takes a defining-class argument.

Fastcall details

METH_FASTCALL passes arguments as a C array rather than packing them into a tuple. The signature is:

PyObject* func(PyObject *self,
PyObject *const *args,
Py_ssize_t nargs);

METH_FASTCALL | METH_KEYWORDS:

PyObject* func(PyObject *self,
PyObject *const *args,
Py_ssize_t nargs,
PyObject *kwnames);

kwnames is a tuple of keyword argument names corresponding to the last len(kwnames) entries of args. args[nargs - len(kwnames)] is the first keyword value.

Vectorcall (PEP 590)

Vectorcall extends fastcall to callable objects in general, not just methods. A type with Py_TPFLAGS_HAVE_VECTORCALL has a function pointer at vectorcall_offset bytes into the instance.

typedef PyObject* (*vectorcallfunc)(PyObject *callable,
PyObject *const *args,
size_t nargsf,
PyObject *kwnames);
ComponentMeaning
callableThe callable itself.
argsArgument array.
nargsfNumber of positional args, OR-ed with PY_VECTORCALL_ARGUMENTS_OFFSET.
kwnamesTuple of keyword names; trailing entries in args correspond.

PY_VECTORCALL_ARGUMENTS_OFFSET indicates the caller reserved one slot before args so the callee can prepend self without copying. This is how bound methods avoid a copy.

Argument parsing

Most built-in functions use one of the helpers:

HelperPurpose
PyArg_ParseTuple(args, format, ...)Parse positional tuple.
PyArg_ParseTupleAndKeywords(args, kwargs, format, kwlist, ...)Tuple + dict.
_PyArg_ParseStack(args, nargs, format, ...)Parse fastcall positional.
_PyArg_ParseStackAndKeywords(args, nargs, kwnames, parser, ...)Fastcall + kwnames.
Argument ClinicCompile-time generator producing optimal parsers.

Format characters

CharC typePython type
sconst char *str (UTF-8, no embedded null).
s*Py_bufferstr or buffer.
s#const char *, Py_ssize_tstr with length.
zconst char *str or None.
yconst char *bytes.
y*Py_bufferbytes-like (read-only).
y#const char *, Py_ssize_tbytes with length.
SPyObject *bytes.
YPyObject *bytearray.
uPy_UCS4 *str (deprecated).
UPyObject *str.
bunsigned charint.
Bunsigned charint (truncating).
hshortint.
Hunsigned shortint.
iintint.
Iunsigned intint.
llongint.
kunsigned longint.
Llong longint.
Kunsigned long longint.
nPy_ssize_tint.
ccharlength-1 bytes.
Cintlength-1 str (Py_UCS4 code point).
ffloatfloat.
ddoublefloat.
DPy_complexcomplex.
OPyObject *any object.
O!PyTypeObject *, PyObject *object of exact type.
O&converter, void *object passed through converter.
pintbool (predicate).
(...)nestedTuple.
|-Following arguments are optional.
$-Following arguments are keyword-only.
:-Function name prefix.
;-Error message prefix.

Frame layout

A _PyInterpreterFrame is laid out:

FieldDescription
previousPointer to the previous frame.
executable / f_executableCode object or executor.
instr_ptrNext instruction.
stacktopStack pointer offset.
f_globals, f_builtins, f_localsNamespace references.
f_frame_objLazy Python-level frame proxy.
localsplus[]Inline storage for locals, cells, free vars, eval stack.

localsplus[] is laid out: locals first, then cells, then free variables, then the eval stack. co_nlocals, co_ncellvars, co_nfreevars, and co_stacksize give the offsets.

Eval stack

The eval stack is part of the frame's localsplus[]. A Python function's co_stacksize is the maximum depth statically computed by Python/flowgraph.c. Each PyObject* slot on the stack is a strong reference.

Reference counting on the stack

Operation
Pushing a value: caller transfers ownership of one strong ref.
Popping a value: callee receives ownership.
Borrowed semantics: special opcodes like LOAD_FAST_BORROW push non-owning refs that must not outlive the local.

Reference counting on the stack is invariant-preserving even when exceptions unwind: each unwind step pops and DECREFs the stack down to a known good depth from the exception table.

Internal calling helpers

HelperUsed for
PyObject_CallOneArg(c, a)One positional argument.
PyObject_CallNoArgs(c)No arguments.
PyObject_CallMethodObjArgsBound method, var args.
PyObject_Vectorcall(callable, args, nargsf, kwnames)Vectorcall fast path.
_PyObject_FastCallDict(c, args, n, kw)Build-and-call when caller has a dict.

Cross-interpreter ABI (PEP 554)

Multiple interpreters in one process require careful ABI separation:

Rule
Static types may be shared.
Heap types must not cross interpreter boundaries.
Cross-interpreter calls go via _xxsubinterpreters or interpreters.queues.
Per-interpreter state lives in PyInterpreterState.

Stable ABI

CPython exposes a limited API (Py_LIMITED_API) for compiled extensions that need to work across minor versions. The stable ABI omits anything internal-by-design (frame internals, type slot layout, GC structures, vectorcall offset).

gopy does not implement the C extension ABI at all (see Status -> Non-goals).

Gopy status

ConventionState
METH_VARARGS / METH_KEYWORDSBuilt-ins use the Go-side objects.BuiltinFunction shape; semantics match.
METH_FASTCALLImplemented through the same Go shape; the VM does not pack arguments into a tuple.
VectorcallInternal fast path for built-in callables.
PyArg_ParseTuple format stringsGopy uses Go-style argument parsing; format-string parity is N/A.
Frame layoutMirrors CPython's localsplus[] design.
Eval stack semanticsIdentical.

Reference

  • Include/cpython/methodobject.h. Method flag definitions.
  • Objects/call.c. The dispatch logic.
  • PEP 590 (Vectorcall).
  • VM internals.
  • Frame internals.