Skip to main content

Objects/capsule.c

cpython 3.14 @ ab2d84fe1023/Objects/capsule.c

A PyCapsule is a thin Python object that wraps an arbitrary void * pointer together with a string name and an optional destructor callback. The mechanism exists so that C extension modules can export internal APIs to other extension modules without exposing a public Python interface. NumPy, for example, uses a capsule to publish its C-level array API: a consumer calls PyCapsule_Import, gets back the void *, and casts it to a function-pointer table.

The object layout is a four-field C struct: pointer, name, destructor, and context. The name is an ASCII string literal stored by pointer, not copied, so the caller is responsible for keeping it alive. The destructor, if set, is called with the capsule itself as argument during tp_finalize, giving the owner a chance to release the wrapped resource. The context field is a spare void * slot that the owner can use for any purpose without affecting the capsule's identity.

The public API pairs creation with a family of typed getters. Every getter validates the capsule name before returning a value, raising PyCapsuleError when the name does not match. This name check is the primary safety mechanism: it prevents a consumer from accidentally reading a pointer created by a different library even if both capsules end up in the same module namespace.

Map

LinesSymbolRolegopy
1-40PyCapsule struct + capsule_checkobject layout and internal type guardnot ported
41-80PyCapsule_Newallocate and initialise a capsulenot ported
81-120PyCapsule_GetPointervalidate name and return void *not ported
121-155PyCapsule_GetName / PyCapsule_SetNameread/write the name fieldnot ported
156-190PyCapsule_GetDestructor / PyCapsule_SetDestructorread/write the destructornot ported
191-230PyCapsule_GetContext / PyCapsule_SetContextread/write the spare context slotnot ported
231-290PyCapsule_Importresolve "package.module.attrname" to a pointernot ported

Reading

Object layout and allocation (lines 1 to 80)

cpython 3.14 @ ab2d84fe1023/Objects/capsule.c#L1-80

The PyCapsule C struct sits at the top of the file, immediately after the includes. It carries four fields: void *pointer, const char *name, PyCapsule_Destructor destructor, and void *context. PyCapsule_New allocates the object with PyObject_New, then copies all four arguments directly into those fields. The name pointer is stored as-is, so callers typically pass a string literal with static storage duration.

typedef struct {
PyObject_HEAD
void *pointer;
const char *name;
PyCapsule_Destructor destructor;
void *context;
} PyCapsule;

Pointer retrieval and name validation (lines 81 to 120)

cpython 3.14 @ ab2d84fe1023/Objects/capsule.c#L81-120

PyCapsule_GetPointer is the most-called function in the file. It first checks that the argument is actually a PyCapsule with PyCapsule_CheckExact, then compares the stored name against the requested name. The comparison uses strcmp when both are non-NULL, accepts a NULL expected name as a wildcard, and raises PyCapsuleError on any mismatch. Only after both checks pass does it return capsule->pointer.

void *
PyCapsule_GetPointer(PyObject *op, const char *name)
{
PyCapsule *capsule = capsule_check(op); /* type check + NULL guard */
if (!capsule) return NULL;
if (name != NULL && capsule->name != NULL) {
if (strcmp(name, capsule->name) != 0) {
PyErr_SetString(PyExc_PyCapsuleError, "PyCapsule_GetPointer: name mismatch");
return NULL;
}
}
return capsule->pointer;
}

Context and destructor accessors (lines 156 to 230)

cpython 3.14 @ ab2d84fe1023/Objects/capsule.c#L156-230

The context and destructor accessors follow the same pattern as the pointer getter but skip the name check, since neither field participates in the capsule's identity. The setter variants (PyCapsule_SetContext, PyCapsule_SetDestructor) perform the same type check and then write directly into the struct. There is no reference counting involved because all four fields are raw C pointers, not PyObject * references.

int
PyCapsule_SetContext(PyObject *op, void *context)
{
PyCapsule *capsule = capsule_check(op);
if (!capsule) return -1;
capsule->context = context;
return 0;
}

Import by dotted name (lines 231 to 290)

cpython 3.14 @ ab2d84fe1023/Objects/capsule.c#L231-290

PyCapsule_Import accepts a string of the form "package.module.attrname". It splits off the final component as the attribute name, imports the leading dotted module path with PyImport_ImportModule, then calls PyObject_GetAttrString to retrieve the capsule attribute. After validating the result with PyCapsule_GetPointer, it returns the raw pointer. This is the entry point used by binary extensions that consume another extension's C API, such as a SciPy module importing NumPy's array API capsule.

void *
PyCapsule_Import(const char *name, int no_block)
{
/* split "a.b.attr" -> module "a.b", attr "attr" */
...
module = PyImport_ImportModule(module_name);
object = PyObject_GetAttrString(module, attrs[n_attrs - 1]);
return PyCapsule_GetPointer(object, name);
}

gopy mirror

Not yet ported.