Skip to content

Instantly share code, notes, and snippets.

@RezSat
Last active June 18, 2025 13:05
Show Gist options
  • Save RezSat/af3158ac13c36b98a0b8194c24a75773 to your computer and use it in GitHub Desktop.
Save RezSat/af3158ac13c36b98a0b8194c24a75773 to your computer and use it in GitHub Desktop.
To illustrate the fundamental PyObject structure and its accessible fields, consider the following C extension. This example creates a Python integer object and then inspects its internal ob_refcnt and ob_type->tp_name fields using the CPython API macros. C
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include <stdio.h> // For PySys_WriteStdout
// Define a simple C function that creates a Python integer
// and prints its ob_refcnt and ob_type->tp_name
static PyObject*
inspect_int_object(PyObject *self, PyObject *args) {
PyObject *py_int_obj;
long value;
// Parse arguments: expect a single long integer
if (!PyArg_ParseTuple(args, "l", &value)) {
return NULL; // Error occurred
}
// Create a Python integer object
py_int_obj = PyLong_FromLong(value);
if (py_int_obj == NULL) {
return NULL; // Error creating object
}
// Access ob_refcnt and ob_type using macros
Py_ssize_t ref_count = Py_REFCNT(py_int_obj);
PyTypeObject *type_obj = Py_TYPE(py_int_obj);
const char *type_name = type_obj->tp_name;
// Print the information
PySys_WriteStdout("Object: %ld\n", value);
PySys_WriteStdout(" Reference Count: %zd\n", ref_count);
PySys_WriteStdout(" Type Name: %s\n", type_name);
// Decrement the reference count for the object we created
// This is crucial for proper memory management.
Py_DECREF(py_int_obj);
Py_RETURN_NONE; // Return None (increments its refcount)
}
// ---
// Corrected Module method definitions
// Declare MyInspectMethods as an ARRAY of PyMethodDef
static PyMethodDef MyInspectMethods[] = {
{"inspect_int", inspect_int_object, METH_VARARGS,
"Inspects a Python integer object's internal PyObject fields."},
{NULL, NULL, 0, NULL} // Sentinel
};
// ---
// Module definition structure for Python 3
static struct PyModuleDef inspectmodule = {
PyModuleDef_HEAD_INIT,
"inspect_internals", // Module name
"A module to inspect CPython object internals.", // Module docstring
-1, // Size of per-interpreter state of the module, -1 means global state
MyInspectMethods // Module methods (now correctly a pointer to the array)
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment