Skip to main content

Python/modsupport.c

Source:

cpython 3.14 @ ab2d84fe1023/Python/modsupport.c

modsupport.c provides the C extension author's toolkit: functions for creating modules, adding attributes, and marshalling between Python objects and C values.

Map

LinesSymbolRole
1-100PyModule_New, PyModule_NewObjectCreate a module with a given name
101-300PyModule_AddObject, PyModule_AddIntConstantAdd attributes to a module
301-600Py_BuildValueBuild a Python object from a C format string
601-900PyArg_ParseTuple, PyArg_ParseTupleAndKeywordsParse Python args into C variables
901-1200vgetargs1Internal va_list parser used by the above

Reading

PyModule_New

// CPython: Python/modsupport.c:42 PyModule_NewObject
PyObject *
PyModule_NewObject(PyObject *name)
{
PyModuleObject *m = (PyModuleObject *)PyModule_Type.tp_alloc(&PyModule_Type, 0);
m->md_dict = PyDict_New();
if (PyDict_SetItemString(m->md_dict, "__name__", name) < 0) ...
if (PyDict_SetItemString(m->md_dict, "__doc__", Py_None) < 0) ...
if (PyDict_SetItemString(m->md_dict, "__package__", Py_None) < 0) ...
if (PyDict_SetItemString(m->md_dict, "__loader__", Py_None) < 0) ...
if (PyDict_SetItemString(m->md_dict, "__spec__", Py_None) < 0) ...
return (PyObject *)m;
}

PyModule_AddObject

// CPython: Python/modsupport.c:165 PyModule_AddObjectRef
int
PyModule_AddObjectRef(PyObject *m, const char *name, PyObject *value)
{
PyObject *dict = PyModule_GetDict(m);
return PyDict_SetItemString(dict, name, value);
}

The AddObjectRef variant (3.10+) does not steal a reference; the older AddObject does. Extension authors should prefer AddObjectRef.

Py_BuildValue format codes

// CPython: Python/modsupport.c:320 Py_BuildValue
PyObject *
Py_BuildValue(const char *format, ...)
{
/* Format codes:
* 'i' / 'l' → PyLong_FromLong
* 'd' → PyFloat_FromDouble
* 's' → PyUnicode_FromString (NULL → None)
* 'y' → PyBytes_FromString
* 'O' → Py_NewRef (an existing PyObject *)
* 'N' → as 'O' but steals reference
* '()', '[]' → build tuple / list from sub-format
*/
return vbuildvalue(format, vargs);
}

Py_BuildValue("(ii)", 1, 2) returns (1, 2). "()" with no enclosed codes returns an empty tuple.

PyArg_ParseTuple

// CPython: Python/modsupport.c:640 PyArg_ParseTuple
int
PyArg_ParseTuple(PyObject *args, const char *format, ...)
{
va_list vargs;
va_start(vargs, format);
retval = vgetargs1(args, format, &vargs, 0 /* flags */);
va_end(vargs);
return retval;
}

Format codes for parsing:

  • iint *
  • llong *
  • ddouble *
  • sconst char ** (points into Python string; do not free)
  • y*Py_buffer * (bytes-like object)
  • OPyObject ** (any object)
  • O!PyObject ** with type check
  • | — remaining args are optional
  • $ — remaining args are keyword-only

PyArg_ParseTupleAndKeywords

// CPython: Python/modsupport.c:720 PyArg_ParseTupleAndKeywords
int
PyArg_ParseTupleAndKeywords(PyObject *args, PyObject *kw,
const char *format, char **kwlist, ...)
{
return vgetargs1_impl(args, kw, format, kwlist, &vargs, FLAG_SIZE_T);
}

kwlist is a NULL-terminated array of keyword names. The compiler's clinic tool generates both kwlist and the format string from a function signature.

gopy notes

PyModule_New is objects.NewModule. AddObjectRef calls module.Dict().Set(name, value). Py_BuildValue and PyArg_ParseTuple are used only in the C extension shim layer; gopy's native Go modules use typed Go function signatures directly without format strings.