Почему PyObject* может указывать на любой объект в Python?
В исходном коде Python есть несколько определений макросов, таких как:
#define PyObject_HEAD \
int ob_refcnt; \
struct _typeobject *ob_type;
#define PyObject_VAR_HEAD \
PyObject_HEAD \
int ob_size;
typedef struct _object {
PyObject_HEAD
} PyObject;
typedef struct _object {
PyObject_HEAD
long ob_ival;
} PyIntObject;
typedef struct {
PyObject_VAR_HEAD
} PyVarObject;
Вопрос в том, почему PyObject* может указывать на каждый объект (например, PyIntObject, PyVarObject) в python?
2 ответа
Каждая структура для различных типов объектов Python имеет экземпляр PyObject_HEAD
в качестве первого члена (или первого члена первого члена и т. д.).
Этот подобъект-член гарантированно находится по тому же адресу, что и полный объект.
PyObject_HEAD*
указывает на этот дочерний объект, но может быть приведен к полному типу один раз ob_type
был проверен, чтобы выяснить, что такое полный тип.
Этот прием не уникален для CPython - он часто используется для реализации ограниченного вида наследования в C. По сути, вы моделируете отношение "является X" с помощью "имеет X в начале".
Так как PyObject_HEAD
ВСЕГДА первый член структуры, не затронутый конкретным базовым типом. Указатель, конечно, будет приведен в порядок.