You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CPython中ctypes.c_int与ctypes.py_object(整数)的内部差异

CPython 3.9.6中整数PyObject与ctypes.c_int的内部表示差异

1. ctypes.c_int对象的内存解析

你执行的代码:

>>> x = 1234
>>> c1 = c_int(x)
>>> id(c1)
4339302720
>>> type(c1)
<class 'ctypes.c_int'>
>>> c1.value
1234
>>> cast(addressof(c1),POINTER(c_int)).contents.value
1234
  • c1是Python层面的ctypes.c_int对象,id(c1)返回的是这个PyObject在Python堆中的内存地址。
  • ctypes的基础数值类型(如c_int)内部布局里,直接嵌入了对应C类型的数值存储区域。addressof(c1)获取的就是这个嵌入的C整数的内存起始地址,所以用POINTER(c_int)解析后能直接读取到1234,你的推测正确——c1.value内部就是直接读取这块C数值存储区域的值。

2. ctypes.py_object对象的内存解析

你执行的代码:

>>> c2 = cast(id(x),py_object)
>>> id(c2)
4337584448
>>> type(c2)
<class 'ctypes.py_object'>
>>> c2.value
1234
>>> cast(addressof(c2),POINTER(c_int)).contents.value
43544656

针对你的疑问逐一解答:

  • c2确实是ctypes.py_object类型的PyObject,id(c2)是它在Python堆中的内存地址,和c1一样是独立的Python对象。
  • ctypes.py_object的核心作用是存储指向另一个PyObject的指针,而非直接存储数值。addressof(c2)拿到的是这个指针的存储地址,你用POINTER(c_int)解析得到的43544656,本质就是原整数对象x的内存地址(即id(x)的数值)——如果是64位系统,这里读取的是指针的低4字节(小端模式下),但核心是这个值是x的地址,而非1234本身。
  • 当访问c2.value时,ctypes.py_object会把内部存储的指针当作目标PyObject的地址,直接引用对应的Python对象(也就是x),所以返回的结果就是1234。

核心差异总结

  • ctypes.c_int:是C语言int类型的Python包装器,内部嵌入C风格的数值存储,和Python原生整数是完全独立的实体,value直接对应C数值。
  • Python原生整数(PyLongObject):CPython中所有整数都是PyLongObject结构体实例,包含PyObject通用头部(引用计数、类型指针等),后续字段存储整数的实际数值(多位数用数组存储),id(x)返回的是这个结构体的内存起始地址。
  • ctypes.py_object:是ctypes用于传递Python对象指针的包装类型,内部存储目标PyObject的地址,value属性通过该地址取出对应的Python对象。

权威参考依据

  • CPython官方文档的ctypes模块章节,明确了各类ctypes类型的设计目的,其中py_object用于持有Python对象引用。
  • CPython源码:Include/longobject.h定义了PyLongObject的结构;Modules/_ctypes/ctypes.h及相关实现文件,定义了ctypes包装对象的底层结构,包括py_object对应的内部存储逻辑。

内容的提问来源于stack exchange,提问作者neowise

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 10:03:21