Skip to content

70. Calling Python From C

PyObject_Call, PyObject_CallNoArgs, argument tuple construction, and error checking after calling into Python.

Calling Python from C means using the CPython C API to invoke Python objects from native code. The callable may be a function, method, class, instance with __call__, bound method, coroutine function, or any other object accepted by Python’s call protocol.

This operation appears in both extension and embedding code.

extension module:
    Python calls C
        C calls Python callback

embedded application:
    C application starts Python
        C calls Python module function

At the C level, Python calls are ordinary object operations. A callable is a PyObject *. Arguments are Python objects. The result is a new PyObject *, or NULL if an exception occurred.

70.1 Basic Call Model

The simplest call shape is:

PyObject *result =
    PyObject_CallObject(callable, args);

Where:

ValueMeaning
callablePython object to call
argsTuple of positional arguments, or NULL
resultNew reference on success
NULLFailure with exception set

Conceptually:

C code
    owns callable reference
    builds argument tuple
    calls callable
    receives result object
    handles exception or decrefs result

This corresponds to Python code like:

result = callable(*args)

70.2 Checking Callability

Before calling an object, native code can check:

if (!PyCallable_Check(callable)) {
    PyErr_SetString(PyExc_TypeError, "object is not callable");
    return NULL;
}

This mirrors:

callable(obj)

A callable may be:

Python function
built-in function
bound method
class
callable instance
C extension function
functools.partial object

Do not assume the object is a function. Call the protocol.

70.3 Building Positional Arguments

PyObject_CallObject expects a tuple.

Example:

PyObject *args = PyTuple_New(2);
if (args == NULL) {
    return NULL;
}

PyObject *a = PyLong_FromLong(10);
if (a == NULL) {
    Py_DECREF(args);
    return NULL;
}

PyObject *b = PyLong_FromLong(20);
if (b == NULL) {
    Py_DECREF(a);
    Py_DECREF(args);
    return NULL;
}

PyTuple_SET_ITEM(args, 0, a);  /* steals a */
PyTuple_SET_ITEM(args, 1, b);  /* steals b */

PyObject *result = PyObject_CallObject(callable, args);
Py_DECREF(args);

if (result == NULL) {
    return NULL;
}

return result;

The tuple owns the argument references after PyTuple_SET_ITEM.

70.4 Safer Argument Construction

PyTuple_Pack is simpler and safer for small argument lists.

PyObject *a = PyLong_FromLong(10);
if (a == NULL) {
    return NULL;
}

PyObject *b = PyLong_FromLong(20);
if (b == NULL) {
    Py_DECREF(a);
    return NULL;
}

PyObject *args = PyTuple_Pack(2, a, b);

Py_DECREF(a);
Py_DECREF(b);

if (args == NULL) {
    return NULL;
}

PyObject *result = PyObject_CallObject(callable, args);
Py_DECREF(args);

return result;

PyTuple_Pack does not steal references. It increments references for inserted items. The caller must decref a and b.

70.5 Calling With No Arguments

For no arguments:

PyObject *result = PyObject_CallNoArgs(callable);

This is clearer and avoids constructing an empty tuple manually.

Equivalent Python:

result = callable()

Always check:

if (result == NULL) {
    return NULL;
}

70.6 Calling With One Argument

For one positional argument:

PyObject *arg = PyLong_FromLong(42);
if (arg == NULL) {
    return NULL;
}

PyObject *result = PyObject_CallOneArg(callable, arg);
Py_DECREF(arg);

if (result == NULL) {
    return NULL;
}

return result;

This avoids tuple construction in many paths.

Equivalent Python:

result = callable(42)

70.7 Calling With Keyword Arguments

Use PyObject_Call.

PyObject *args = NULL;
PyObject *kwargs = NULL;
PyObject *result = NULL;

args = PyTuple_Pack(1, path_obj);
if (args == NULL) {
    goto error;
}

kwargs = PyDict_New();
if (kwargs == NULL) {
    goto error;
}

if (PyDict_SetItemString(kwargs, "strict", Py_True) < 0) {
    goto error;
}

result = PyObject_Call(callable, args, kwargs);
if (result == NULL) {
    goto error;
}

Py_DECREF(args);
Py_DECREF(kwargs);
return result;

error:
Py_XDECREF(args);
Py_XDECREF(kwargs);
return NULL;

Equivalent Python:

result = callable(path, strict=True)

PyDict_SetItemString does not steal references. Py_True is a borrowed singleton, and the dict takes its own reference internally.

70.8 PyObject_CallFunction

PyObject_CallFunction builds arguments from a format string.

PyObject *result =
    PyObject_CallFunction(callable, "si", "name", 42);

Equivalent Python:

result = callable("name", 42)

Common format units:

FormatMeaning
sC string to Python str
iC int to Python int
lC long to Python int
dC double to Python float
OExisting PyObject *
NExisting PyObject *, steals reference

Use this API carefully. It is compact, but ownership can become less obvious than explicit object construction.

70.9 Calling Methods

To call a named method:

PyObject *result =
    PyObject_CallMethod(obj, "close", NULL);

Equivalent Python:

result = obj.close()

With arguments:

PyObject *result =
    PyObject_CallMethod(obj, "write", "s", "hello");

Equivalent Python:

result = obj.write("hello")

For performance-sensitive code, avoid repeated string method lookup inside tight loops. Cache the method or use lower-level APIs carefully.

70.10 Attribute Lookup Before Calling

Calling a method manually has two steps:

PyObject *method =
    PyObject_GetAttrString(obj, "process");
if (method == NULL) {
    return NULL;
}

PyObject *result =
    PyObject_CallOneArg(method, arg);

Py_DECREF(method);

if (result == NULL) {
    return NULL;
}

return result;

This mirrors:

method = obj.process
result = method(arg)

The attribute lookup may run Python code through descriptors, properties, or custom __getattribute__.

70.11 Error Handling

If a call fails, the result is NULL and an exception is set.

PyObject *result = PyObject_CallObject(callable, args);
if (result == NULL) {
    return NULL;
}

Propagating the error is often correct.

To print and clear it in embedding code:

if (result == NULL) {
    PyErr_Print();
    return -1;
}

To fetch it:

PyObject *type = NULL;
PyObject *value = NULL;
PyObject *tb = NULL;

PyErr_Fetch(&type, &value, &tb);
PyErr_NormalizeException(&type, &value, &tb);

/* inspect or translate */

Py_XDECREF(type);
Py_XDECREF(value);
Py_XDECREF(tb);

Extension functions normally propagate errors. Embedded applications often translate them into host diagnostics.

70.12 Result Ownership

A successful call returns a new reference.

PyObject *result = PyObject_CallNoArgs(callable);
if (result == NULL) {
    return NULL;
}

/* use result */

Py_DECREF(result);
Py_RETURN_NONE;

If returning the result to Python, pass ownership upward:

return result;

Do not decref before returning.

Incorrect:

Py_DECREF(result);
return result;  /* use-after-free */

70.13 Callback Storage

Native objects often store Python callbacks.

Example structure:

typedef struct {
    PyObject_HEAD
    PyObject *callback;
} HandlerObject;

Setter:

static int
Handler_set_callback(HandlerObject *self, PyObject *value)
{
    if (value != NULL && !PyCallable_Check(value)) {
        PyErr_SetString(PyExc_TypeError, "callback must be callable");
        return -1;
    }

    Py_XINCREF(value);
    Py_XDECREF(self->callback);
    self->callback = value;
    return 0;
}

Deallocator:

static void
Handler_dealloc(HandlerObject *self)
{
    Py_XDECREF(self->callback);
    Py_TYPE(self)->tp_free((PyObject *)self);
}

The object owns a strong reference to the callback.

70.14 Calling Stored Callbacks

static PyObject *
Handler_fire(HandlerObject *self, PyObject *args)
{
    if (self->callback == NULL) {
        PyErr_SetString(PyExc_RuntimeError, "no callback set");
        return NULL;
    }

    return PyObject_CallObject(self->callback, args);
}

If the callback fails, the exception propagates naturally.

This gives Python code normal traceback behavior.

70.15 Borrowed References Around Calls

Calling Python can execute arbitrary code. That code can mutate containers, release references, run finalizers, import modules, trigger garbage collection, or call back into the extension.

This is unsafe:

PyObject *item = PyList_GetItem(list, 0);  /* borrowed */

PyObject *result = PyObject_CallNoArgs(callback);
if (result == NULL) {
    return NULL;
}

/* item may no longer be valid */

Safer:

PyObject *item = PyList_GetItem(list, 0);
if (item == NULL) {
    return NULL;
}

Py_INCREF(item);

PyObject *result = PyObject_CallNoArgs(callback);
if (result == NULL) {
    Py_DECREF(item);
    return NULL;
}

Py_DECREF(result);

/* item is still valid */

Py_DECREF(item);
Py_RETURN_NONE;

Before calling Python, own every object you need afterward.

70.16 Reentrant Calls

Calling Python from C may reenter your extension.

Example:

C extension method starts
    calls Python callback
        callback calls same C extension object
            extension sees partially updated state

This can break invariants.

Guard state explicitly:

if (self->running) {
    PyErr_SetString(PyExc_RuntimeError, "reentrant call");
    return NULL;
}

self->running = 1;

PyObject *result = PyObject_CallNoArgs(callback);

self->running = 0;

Use cleanup-safe patterns so flags are reset even on failure.

70.17 Cleanup-Safe Reentrancy Guard

static PyObject *
run_callback(HandlerObject *self)
{
    PyObject *result = NULL;

    if (self->running) {
        PyErr_SetString(PyExc_RuntimeError, "reentrant call");
        return NULL;
    }

    self->running = 1;

    result = PyObject_CallNoArgs(self->callback);

    self->running = 0;

    if (result == NULL) {
        return NULL;
    }

    return result;
}

For more complex functions, use a single cleanup label:

self->running = 1;

result = PyObject_CallNoArgs(self->callback);
if (result == NULL) {
    goto done;
}

/* more work */

done:
self->running = 0;
return result;

70.18 Calling Python From Native Threads

A native thread must hold the GIL before calling Python APIs.

PyGILState_STATE state;

state = PyGILState_Ensure();

/* safe to call Python APIs */

PyGILState_Release(state);

Example:

void
worker_thread_callback(PyObject *callback)
{
    PyGILState_STATE state;
    PyObject *result;

    state = PyGILState_Ensure();

    result = PyObject_CallNoArgs(callback);
    if (result == NULL) {
        PyErr_Print();
    } else {
        Py_DECREF(result);
    }

    PyGILState_Release(state);
}

The callback object must remain alive while the native thread may use it. Store an owned reference.

70.19 GIL and Long Native Work

If C code calls Python, then performs long native work, separate the phases.

PyObject *result = PyObject_CallNoArgs(callback);
if (result == NULL) {
    return NULL;
}

/* convert result to native data while GIL is held */

Py_BEGIN_ALLOW_THREADS

long_native_compute();

Py_END_ALLOW_THREADS

Py_DECREF(result);
Py_RETURN_NONE;

Do not touch Python objects while the GIL is released.

70.20 Vectorcall

Modern CPython uses vectorcall for efficient calls.

The idea is to pass arguments as a C array rather than packing them into a tuple.

Conceptual shape:

callable
args[0]
args[1]
...
nargs
kwargs names

This reduces temporary allocation.

Public APIs include helpers such as:

PyObject_Vectorcall

where available for the target API level.

Vectorcall matters most in tight call-heavy paths. For ordinary extension code, PyObject_CallNoArgs, PyObject_CallOneArg, and PyObject_Call are often clearer.

70.21 Classes Are Callables

Calling a class constructs an instance.

PyObject *obj =
    PyObject_CallObject((PyObject *)type, args);

Equivalent Python:

obj = Type(*args)

This invokes the normal Python construction protocol:

type.__call__
    tp_new / __new__
    tp_init / __init__

Do not bypass this unless you need low-level allocation semantics.

70.22 Coroutine Functions

Calling an async function does not run it to completion. It returns a coroutine object.

Python:

coro = async_func()

C:

PyObject *coro = PyObject_CallNoArgs(async_func);
if (coro == NULL) {
    return NULL;
}

The coroutine must then be awaited or scheduled by an event loop.

Embedding code that calls async Python must integrate with asyncio or another scheduler. Calling the function itself only creates the coroutine object.

70.23 Calling Python During Finalization

Avoid calling Python during interpreter shutdown unless you know the runtime is still valid.

During finalization:

modules may be cleared
globals may be set to None
imports may fail
destructors may run in unusual order
threads may be stopping

Callbacks from C destructors are especially dangerous during shutdown.

A safe design avoids arbitrary Python calls from native finalizers.

70.24 Common Bugs

BugCause
Passing non-tuple to PyObject_CallObjectIncorrect argument construction
Forgetting to decref resultLeak
Decrefing result before returnUse-after-free
Holding borrowed reference across callbackDangling pointer
Calling without GILCrash or corruption
Ignoring NULL resultContinuing after exception
Reentrant callback corrupts stateMissing guard
Calling async function expecting resultGot coroutine object
Using Python during shutdownFinalization crash

70.25 Practical Checklist

Before calling Python from C:

QuestionRequired answer
Do I hold the GIL?Yes
Is the object callable?Check if uncertain
Are arguments valid Python objects?Yes
Are borrowed references protected across the call?Yes
Is NULL result handled?Yes
Is returned reference decrefed or returned?Yes
Can the callback reenter my code?Guard if needed
Can the call happen during shutdown?Avoid or handle explicitly

70.26 Chapter Summary

Calling Python from C uses the same object protocol as Python code. A callable is a PyObject *, arguments are Python objects, and the result is a new reference or NULL with an exception set.

The main APIs are PyObject_Call, PyObject_CallObject, PyObject_CallNoArgs, PyObject_CallOneArg, PyObject_CallFunction, and PyObject_CallMethod.

The hard parts are not the call itself. The hard parts are ownership, error handling, borrowed-reference lifetime, reentrancy, GIL discipline, async behavior, and interpreter shutdown.