首页
/ CPython C API 中的公共对象结构:PyObject、PyMethodDef 与 PyMemberDef 深度解析

CPython C API 中的公共对象结构:PyObject、PyMethodDef 与 PyMemberDef 深度解析

2026-09-06 12:13:09作者:裴锟轩Denise

CPython 的 C API 文档将 Doc/c-api/structures.rst 作为所有 C 扩展开发者的"对象模型总纲":它定义了每个 Python 对象内存布局的公共头部(PyObject / PyVarObject)、用 C 实现 Python 可调用对象的 PyMethodDef 与各调用约定,以及把 C 结构体成员暴露为 Python 属性的 PyMemberDef / PyGetSetDef。本文完整继承该文档的核心内容,并结合 CPython 仓库头文件(Include/object.hInclude/methodobject.hInclude/descrobject.h 等)逐条剖析其内存布局、宏展开与实现细节,帮助你在编写 C 扩展时正确使用这些结构、宏与函数。

1. 基础对象类型与宏:每个 Python 对象的公共内存头部

CPython 中所有对象在内存表示的开头都共享一小段公共字段。文档 Doc/c-api/structures.rst 开篇即指出:这些字段由 PyObjectPyVarObject 两个类型表示,而这两个类型又由若干宏展开定义,几乎所有其他 Python 对象的定义都会直接或间接用到它们。

1.1 PyObject:对象的引用计数与类型指针

PyObject 是所有对象类型的"基类"。在普通的 release 构建下,它只包含对象的引用计数和指向类型对象的指针。文档强调:没有任何类型真正被声明为 PyObject,但每个 Python 对象指针都可以转换为 PyObject*——这是一种"手工实现的继承"。这段注释同样出现在 Include/object.h 中:

/* Nothing is actually declared to be a PyObject, but every pointer to
 * a Python object can be cast to a PyObject*.  This is inheritance built
 * by hand.  Similarly every pointer to a variable-size Python object can,
 * in addition, be cast to a PyVarObject*.
 */

在标准(非 free-threaded、64 位)构建中,struct _object 的真实布局是:

struct _object {
    _Py_ANONYMOUS union {
#if SIZEOF_VOID_P > 4
        int64_t ob_refcnt_full; /* 在 ARM Clang 上为高效初始化而设 */
        struct {
#  if PY_BIG_ENDIAN
            uint16_t ob_flags;
            uint16_t ob_overflow;
            uint32_t ob_refcnt;
#  else
            uint32_t ob_refcnt;
            uint16_t ob_overflow;
            uint16_t ob_flags;
#  endif
        };
#else
        Py_ssize_t ob_refcnt;  // part of stable ABI; do not change
#endif
        _Py_ALIGNED_DEF(_PyObject_MIN_ALIGNMENT, char) _aligner;
    };
    PyTypeObject *ob_type;  // part of stable ABI; do not change
};

(见 Include/object.hstruct _object 定义。)

各字段说明:

  • ob_refcnt(引用计数):即 Py_REFCNT 宏返回的值。文档明确要求不要直接使用该字段,而应使用 Py_REFCNTPy_INCREFPy_DecRef(文档写作 Py_DecRef)等宏和函数。从源码结构看,在 64 位平台该字段实际是一个 64 位 union 的低 32 位,高 16 位是 ob_overflow(引用计数溢出区)、再高 16 位是 ob_flags(如 static-immortal 标记),这使得引用计数可以用"饱和算术"避免溢出——细节可参考 Include/refcount.h 中关于 immortalization 策略的大段注释。
  • ob_type(对象类型):不要直接访问,应使用 Py_TYPEPy_SET_TYPE
  • ob_mutex(每对象锁):仅存在于 free-threaded 构建(定义了 Py_GIL_DISABLED),3.13 引入。源码中的 free-threaded 布局为:
struct _object {
    _Py_ALIGNED_DEF(_PyObject_MIN_ALIGNMENT, uintptr_t) ob_tid;
    uint16_t ob_flags;
    PyMutex ob_mutex;           // per-object lock
    uint8_t ob_gc_bits;         // gc-related state
    uint32_t ob_ref_local;      // local reference count
    Py_ssize_t ob_ref_shared;   // shared (atomic) reference count
    PyTypeObject *ob_type;
};

文档特别警告:ob_mutex 预留给临界区 API(Py_BEGIN_CRITICAL_SECTION / Py_END_CRITICAL_SECTION)使用,绝不能用 PyMutex_Lock 直接加锁(可能死锁);若扩展需要自己的锁,应在对象结构体中新增独立的 PyMutex 字段。

Stable ABI 的差异:在 free-threaded Stable ABI(abi3t)中 PyObject 是不透明的(opaque),其大小与布局可能随 Python 版本变化;在非 free-threaded 的 abi3ob_refcntob_type 字段可用,但直接访问不推荐。

1.2 PyVarObject:带"长度"的对象头部

PyVarObjectPyObject 的扩展,增加 ob_size 字段,面向一切有长度概念的对象。Include/object.h 中的定义:

struct PyVarObject {
    PyObject ob_base;
    Py_ssize_t ob_size; // Number of items in variable part. Part of stable ABI
};
  • ob_base:公共对象头。通常不直接访问,而是把 PyVarObject 直接转换为 PyObject
  • ob_size:一个"元素个数"字段,其内容应视为对象的内部实现细节。不要直接使用,应使用 Py_SIZE 宏。像 PyObject_NewVar 这样的对象创建函数通常会把它设置为请求的大小(元素数);创建之后可以用 Py_SET_SIZE 存入任意值。若要获取对象对外暴露的、len() 会返回的长度,请使用 PyObject_Length,而不是 ob_size

PyObject_VAR_HEAD 宏的头部注释(见 Include/object.h)也解释了变长容器的内存约定:结构体末尾声明一个含 1 个元素的数组,但实际 malloc 的空间足以容纳 ob_size 个元素;ob_size 是元素数而非字节数。

1.3 PyObject_HEAD 与 PyObject_VAR_HEAD 声明宏

  • PyObject_HEAD:用于声明长度不变的扩展类型,展开为:

    PyObject ob_base;
    
  • PyObject_VAR_HEAD:用于长度逐实例变化的类型,展开为:

    PyVarObject ob_base;
    

1.4 初始化宏与 PyBaseObject_Type

  • PyObject_HEAD_INIT(type):展开为新的 PyObject 类型的初始化值:

    _PyObject_EXTRA_INIT
    1, type,
    
  • PyVarObject_HEAD_INIT(type, size):额外包含 ob_size 字段,展开为:

    _PyObject_EXTRA_INIT
    1, type, size,
    

    其中 1 是初始引用计数,_PyObject_EXTRA_INIT 用于在支持 static-immortal 对象(64 位、非 free-threaded 构建)时填充高位标志位——这在 Include/internal/pycore_object.h 的内部实现中可以看到对应展开。

  • PyTypeObject PyBaseObject_Type:所有其他对象的基类,等价于 Python 中的 object

1.5 身份判断与类型/大小访问 API

文档列出了一组常用的单例判断函数(均为 3.10 新增)与类型/大小访问宏:

API 等价语义 说明
Py_Is(x, y) x is y 判断两个对象是否同一对象;实现即指针比较 (x) == (y)
Py_IsNone(x) x is None 是否为 None 单例
Py_IsTrue(x) x is True 是否为 True 单例
Py_IsFalse(x) x is False 是否为 False 单例
Py_TYPE(o) 返回对象类型;返回的是借用引用(borrowed reference),不得用 Py_DECREF 释放。3.11 起改为 static inline 函数,参数类型不再是 const PyObject*
Py_IS_TYPE(o, type) Py_TYPE(o) == type 3.9 新增
Py_SET_TYPE(o, type) 3.9 新增。无检查、无引用计数地设置类型,属于非常底层操作,可能引发未定义行为;文档建议改用 PyObject_SetAttrString 设置 __class__ 属性
Py_SIZE(o) 读取 ob_size 字段;3.11 起改为 inline static 函数
Py_SET_SIZE(o, size) 3.9 新增,设置 ob_size

关于 Py_SET_TYPE 还有一个容易忽视的引用计数规则(文档原文):如果 type堆类型(heap type),调用者必须为它新建一个引用;如果 o 的旧类型是堆类型,调用者必须释放对该类型的引用。

Py_TYPE 的实现本质在 Include/object.h 中一目了然:

static inline PyTypeObject* _Py_TYPE_impl(PyObject *ob)
{
    return ob->ob_type;
}

而 free-threaded 构建下 Py_REFCNT 的语义完全不同(见 Include/refcount.h):它由线程本地的 ob_ref_local 与共享的原子计数 ob_ref_shared 组合计算得出,Py_REFCNT 返回的是一个"合并视图",这正是不推荐直接访问 ob_refcnt 字段的深层原因。

2. 实现函数与方法:PyMethodDef 与调用约定

2.1 五种 C 函数类型

文档定义了把 Python 可调用对象用 C 实现时的函数类型(其原型可在 Include/methodobject.h 中找到一一对应):

// 最典型的调用约定,参数是两个 PyObject*
PyObject *PyCFunction(PyObject *self, PyObject *args);

// METH_VARARGS | METH_KEYWORDS
PyObject *PyCFunctionWithKeywords(PyObject *self,
                                  PyObject *args,
                                  PyObject *kwargs);

// METH_FASTCALL
PyObject *PyCFunctionFast(PyObject *self,
                          PyObject *const *args,
                          Py_ssize_t nargs);

// METH_FASTCALL | METH_KEYWORDS
PyObject *PyCFunctionFastWithKeywords(PyObject *self,
                                      PyObject *const *args,
                                      Py_ssize_t nargs,
                                      PyObject *kwnames);

// METH_METHOD | METH_FASTCALL | METH_KEYWORDS(3.9 新增)
PyObject *PyCMethod(PyObject *self,
                    PyTypeObject *defining_class,
                    PyObject *const *args,
                    Py_ssize_t nargs,
                    PyObject *kwnames);

通用契约:这些函数返回一个新引用(new reference)作为 Python 层的返回值;若返回 NULL,则应当已经设置了异常。

2.2 PyMethodDef:方法描述结构

PyMethodDef 用于描述扩展类型的一个方法,共 4 个字段(定义见 Include/methodobject.h):

struct PyMethodDef {
    const char  *ml_name;   /* 方法名;NULL 表示 PyMethodDef 数组结束 */
    PyCFunction ml_meth;    /* C 实现指针 */
    int         ml_flags;   /* METH_xxx 标志的组合 */
    const char  *ml_doc;    /* docstring 内容,或 NULL */
};

要点:

  • ml_meth 是 C 函数指针,函数类型可以不同但总是返回 PyObject*;如果不是 PyCFunction 类型,编译器会在方法表中要求显式转换(Include/methodobject.h 提供了 _PyCFunction_CAST 等宏来消除警告)。
  • 虽然 PyCFunction 的第一个参数声明为 PyObject*,但方法实现中通常使用 self 对象的具体 C 类型。

2.3 ml_flags:调用约定标志

ml_flags 是位域,标志分两类:调用约定(calling convention)绑定约定(binding convention)。源码中的位值定义(Include/methodobject.h):

#define METH_VARARGS  0x0001
#define METH_KEYWORDS 0x0002
/* METH_NOARGS 和 METH_O 不得与上面的标志组合使用 */
#define METH_NOARGS   0x0004
#define METH_O        0x0008
#define METH_CLASS    0x0010
#define METH_STATIC   0x0020
#define METH_COEXIST  0x0040
#define METH_FASTCALL 0x0080

调用约定一览:

  1. METH_VARARGS(0x0001):典型约定,函数类型为 PyCFunction。第一个参数是方法的 self 对象(模块函数则是模块对象),第二个参数(惯称 args)是一个元组,代表全部位置参数,通常用 PyArg_ParseTuplePyArg_UnpackTuple 处理。
  2. METH_VARARGS | METH_KEYWORDS:函数必须为 PyCFunctionWithKeywords 类型,接收 selfargskwargs 三个参数;kwargs 是全部关键字参数字典,若无关键字参数可能为 NULL,通常用 PyArg_ParseTupleAndKeywords 处理。
  3. METH_FASTCALL(0x0080,3.7 新增,3.10 起进入稳定 ABI):快速调用约定,仅支持位置参数,函数类型为 PyCFunctionFast。第二个参数是 PyObject* 的 C 数组(而非元组,避免构造元组的开销),第三个参数是数组长度。
  4. METH_FASTCALL | METH_KEYWORDS(3.7 新增):函数类型为 PyCFunctionFastWithKeywords。关键字参数按 vectorcall 协议传递:额外第四参数是一个元组,表示关键字参数名(保证是字符串,无关键字时可能为 NULL);关键字参数的存放在 args 数组中、紧跟位置参数之后。
  5. METH_METHOD | METH_FASTCALL | METH_KEYWORDS(3.9 新增):在上面基础上支持 defining class——包含该方法的类,它可能是 Py_TYPE(self) 的超类。函数类型为 PyCMethod,与 METH_FASTCALL | METH_KEYWORDS 相同,只是在 self 之后多了 defining_class 参数。
  6. METH_NOARGS(0x0004):无参数方法,函数必须仍有 2 个参数,第二个恒为 NULL;未使用的参数可用 Py_UNUSED 抑制编译器警告。
  7. METH_O(0x0008):单对象参数方法,避免用 "O" 格式调用 PyArg_ParseTuple;函数类型为 PyCFunction,第二个 PyObject* 参数就是唯一的实参。

绑定约定(仅用于类方法,不能用于模块函数;一个方法至多设置其一):

  • METH_CLASS(0x0010):第一参数传类型对象而非实例,用于创建类似 @classmethod 装饰器的类方法
  • METH_STATIC(0x0020):第一参数传 NULL,用于创建类似 @staticmethod 装饰器的静态方法

另外还有一个控制方法加载行为的常量:

  • METH_COEXIST(0x0040):该方法的 PyCFunction 会替换已存在的同名定义。默认行为是跳过重复定义;由于 slot 包装器(slot wrapper)先于方法表加载,例如 sq_contains slot 会先生成名为 __contains__ 的包装方法并阻止同名 PyCFunction 加载。设置 METH_COEXIST 后,PyCFunction 将替换包装器对象与 slot 共存——这有助于性能,因为 PyCFunction 的调用比包装器对象调用优化程度更高。

2.4 PyCMethod 与 PyCFunction 对象及其访问 API

  • PyTypeObject PyCMethod_Type:Python C 方法对象对应的类型对象,Python 层即 types.BuiltinMethodType
  • PyCMethod_Check(op) / PyCMethod_CheckExact(op):判断是否为 PyCMethod_Type 实例(或精确类型);前者考虑子类型,两者总是成功。
  • PyCMethod_New(ml, self, module, cls)(3.9 新增):把 mlPyMethodDef*)变成一个 Python 可调用对象。调用者必须保证 ml 的生命周期长于该可调用对象(通常 ml 是 static 变量)。self 会在调用时作为 C 函数的 self 参数传入,可为 NULLmodule 是 Python 字符串,用于设置可调用对象的 __module__ 属性,缺省可设为 NoneNULLcls 作为 defining_class 传入,若 ml->ml_flags 设置了 METH_METHOD 则必须提供。
  • PyTypeObject PyCFunction_Type:对应 types.BuiltinFunctionType
  • PyCFunction_Check / PyCFunction_CheckExact:与 PyCMethod_Check 同理。
  • PyCFunction_NewEx(ml, self, module):等价于 PyCMethod_New(ml, self, module, NULL)
  • PyCFunction_New(ml, self):等价于 PyCMethod_New(ml, self, NULL, NULL)

Objects/methodobject.c 的实现可以印证这条调用链:PyCFunction_NewPyCFunction_NewExPyCMethod_New,即新旧 API 最终汇聚到同一个创建入口。

还有一组属性读取函数(均有带 GET_ 前缀的无检查版本):

函数 无检查版本 说明
PyCFunction_GetFlags(func) PyCFunction_GET_FLAGS 返回创建时传入 ml_flags 的标志值;成功返回标志,失败返回 -1 并设置异常;func 不得为 NULL
PyCFunction_GetFunction(func) PyCFunction_GET_FUNCTION 返回 ml_meth 中的函数指针;失败返回 NULL 并设置异常
PyCFunction_GetSelf(func) PyCFunction_GET_SELF 返回"self"对象(PyModuleDef 创建的模块函数即为模块对象);成功时返回借用引用

3. 访问扩展类型的属性:PyMemberDef 与 PyGetSetDef

3.1 PyMemberDef:把 C 结构体成员映射为 Python 属性

PyMemberDef 描述一个类型中"对应 C 结构体成员"的属性。定义类时,把这样的结构数组(以 NULL 结尾)放进 PyTypeObject.tp_members 槽位。字段依次为:

  • const char* name:成员名。NULL 标记数组结束。字符串必须是静态的,不会拷贝。
  • int type:成员在 C 结构体中的类型,取值见 3.3 节。
  • Py_ssize_t offset:成员在类型对象结构体中的字节偏移。
  • int flags:若干 PyMemberDef.flags 标志按位或组合,见 3.2 节。
  • const char* doc:docstring 或 NULL,字符串应静态,通常用 PyDoc_STR 定义。

默认(flags0)成员可读写;用 Py_READONLY 标志设为只读。某些类型(如 Py_T_STRING)隐含 Py_READONLY。只有 Py_T_OBJECT_EX(以及旧式 T_OBJECT)成员可以被删除。

版本演进PyMemberDef 自 3.12 起始终可用,此前需要 #include "structmember.h"PyMember_GetOne / PyMember_SetOne 同样自 3.12 起始终可用。3.14 起 Py_RELATIVE_OFFSET 也允许用于 "__vectorcalloffset__""__dictoffset__""__weaklistoffset__"

堆类型的特殊偏移成员:对使用 PyType_FromSpec 等方式创建的堆类型,PyMemberDef 可以定义特殊成员 "__vectorcalloffset__"(对应 tp_vectorcalloffset),必须用 Py_T_PYSSIZET 且带 Py_READONLYPy_READONLY | Py_RELATIVE_OFFSET

static PyMemberDef spam_type_members[] = {
    {"__vectorcalloffset__", Py_T_PYSSIZET,
     offsetof(Spam_object, vectorcall), Py_READONLY},
    {NULL}  /* Sentinel */
};

(使用 offsetof 可能需要 #include <stddef.h>。)旧式的 tp_dictoffsettp_weaklistoffset 也可用 "__dictoffset__" / "__weaklistoffset__" 定义,但扩展强烈建议改用 Py_TPFLAGS_MANAGED_DICTPy_TPFLAGS_MANAGED_WEAKREF

配套的单成员访问函数:

  • PyObject* PyMember_GetOne(const char *obj_addr, struct PyMemberDef *m):读取位于 obj_addr 的对象上、由 m 描述的属性;出错返回 NULL
  • int PyMember_SetOne(char *obj_addr, struct PyMemberDef *m, PyObject *o):把该属性设置为 o;成功返回 0,失败返回负值。

3.2 成员标志(Member flags)

标志值定义在 Include/descrobject.h 中:

#define Py_READONLY            (1 << 0)
#define Py_AUDIT_READ          (1 << 1) // Added in 3.10, harmless no-op before that
#define Py_RELATIVE_OFFSET     (1 << 3)
  • Py_READONLY:不可写。
  • Py_AUDIT_READ:读取前发出 object.__getattr__ 审计事件(audit event)。
  • Py_RELATIVE_OFFSET:该条目的 offset 是相对子类型专属数据(而非 PyObject)的偏移。只能作为 Py_tp_members 槽位的一部分,在 PyType_Spec.basicsize 为负数时用 PyType_FromSpec 创建类时使用,且此时是强制的;Python 在类创建时从槽位设置 tp_members 会清除该标志,并把 offset 改写为相对 PyObject 结构体的偏移。

已废弃的历史宏:3.10 起,structmember.h 中的 RESTRICTEDREAD_RESTRICTEDWRITE_RESTRICTED 被弃用——READ_RESTRICTEDRESTRICTED 等价于 Py_AUDIT_READWRITE_RESTRICTED 无效。3.12 起 READONLY 更名为 Py_READONLYPY_AUDIT_READ 更名为带 Py_ 前缀的新名,新名称始终可用;旧头文件 Include/structmember.h 仍保留旧名并作为别名转发:

/* Types */
#define T_SHORT     Py_T_SHORT
...
/* Flags */
#define READONLY            Py_READONLY
#define PY_AUDIT_READ        Py_AUDIT_READ

3.3 成员类型(Member types)

PyMemberDef.type 取下列宏之一,对应不同 C 类型;从 Python 访问时转换为等价 Python 类型,从 Python 设置时转换回 C 类型,无法转换则抛出 TypeErrorValueError。除非标注 (D),用此方式定义的属性不能用 del / delattr 删除:

C 类型 Python 类型
Py_T_BYTE char int
Py_T_SHORT short int
Py_T_INT int int
Py_T_LONG long int
Py_T_LONGLONG long long int
Py_T_UBYTE unsigned char int
Py_T_UINT unsigned int int
Py_T_USHORT unsigned short int
Py_T_ULONG unsigned long int
Py_T_ULONGLONG unsigned long long int
Py_T_PYSSIZET Py_ssize_t int
Py_T_FLOAT float float
Py_T_DOUBLE double float
Py_T_BOOL char(0 或 1) bool
Py_T_STRING (*) const char * str (RO)
Py_T_STRING_INPLACE (*) const char[] str (RO)
Py_T_CHAR (**) char(0-127) str
Py_T_OBJECT_EX (D) PyObject * object

注释:(*) 为以零结尾、UTF-8 编码的 C 字符串;Py_T_STRING 的 C 表示是指针,Py_T_STRING_INPLACE 则把字符串直接存在结构体中。(**) 长度为 1 的字符串,仅接受 ASCII。(RO) 隐含 Py_READONLY。(D) 可删除,删除后指针置为 NULL,读取 NULL 指针抛出 AttributeError

这些宏的数值编号定义在 Include/descrobject.h

#define Py_T_SHORT     0
#define Py_T_INT       1
#define Py_T_LONG      2
#define Py_T_FLOAT     3
#define Py_T_DOUBLE    4
#define Py_T_STRING    5
#define Py_T_CHAR      7   /* 1-character string */
#define Py_T_BYTE      8   /* 8-bit signed int */
#define Py_T_UBYTE     9
#define Py_T_USHORT   10
#define Py_T_UINT      11
#define Py_T_ULONG     12
#define Py_T_STRING_INPLACE    13
#define Py_T_BOOL      14
#define Py_T_OBJECT_EX 16
#define Py_T_LONGLONG  17
#define Py_T_ULONGLONG 18
#define Py_T_PYSSIZET  19      /* Py_ssize_t */

在 3.12 之前的版本中,这些宏只有 #include "structmember.h" 时才可用,且不带 Py_ 前缀(如 T_INT)。该头文件仍提供旧名及两个已弃用类型:

  • T_OBJECT:类似 Py_T_OBJECT_EX,但 NULL 会转换为 None——这会导致 Python 层令人困惑的行为:删除该属性实际上会把它设为 None
  • T_NONE:恒为 None,必须搭配 Py_READONLY 使用。

3.4 PyGetSetDef:定义 getter 与 setter

PyGetSetDef 用于为类型定义"属性式"访问(参见 PyTypeObject.tp_getset 槽位描述),字段为:

  • const char* name:属性名;
  • getter get:获取属性的 C 函数;
  • setter set:可选的赋值/删除函数;为 NULL 时属性只读;
  • const char* doc:可选 docstring;
  • void* closure:可选用户数据指针,为 getter/setter 提供额外上下文。

函数签名与契约:

// getter:接收实例与 closure,成功返回新引用,失败返回 NULL 并设置异常
PyObject *(*getter)(PyObject *, void *);

// setter:接收实例、待设置的值与 closure;
// 属性被删除时第二个参数为 NULL;
// 成功返回 0,失败返回 -1 并设置异常
int (*setter)(PyObject *, PyObject *, void *);

4. 小结与延伸阅读

本文覆盖的 Doc/c-api/structures.rst 是 CPython C API 文档中承上启下的一篇:PyObject/PyVarObjectPyObject_HEAD 系列宏是一切扩展类型内存布局的地基;PyMethodDef 配合 METH_* 标志决定 C 函数如何被 Python 调用;PyMemberDef/PyGetSetDef 则完成 C 字段到 Python 属性的映射。编写 C 扩展时,建议按以下顺序核对仓库源码:

  1. Include/object.hstruct _object / PyVarObject / 各宏的当前实现;
  2. Include/refcount.hPy_REFCNT 在 free-threaded 与稳定 ABI 下的差异实现;
  3. Include/methodobject.hObjects/methodobject.c:调用约定标志位值与 PyCMethod_New 创建链;
  4. Include/descrobject.hInclude/structmember.h:成员类型编号、标志位及旧别名兼容层。

引用计数相关的宏与语义详见文档 Doc/c-api/refcounting.html 对应的 Doc/c-api/refcounting 源文件;对象内存布局的示意图可参考仓库中的 Objects/object_layout_313.png(3.13 布局,供理解 PyObject 头部与 GC 头部的相对位置)。

登录后查看全文
热门项目推荐
相关项目推荐