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

如何对包含ct.Pointer的ctypes.Structure进行Pickling序列化?

解决包含指针的ctypes结构体Pickle序列化问题

你已经迈出了关键一步——给my_array实现了__reduce__方法来处理指针数据的序列化,接下来我们把这个思路扩展到包含这类结构体的my_struct上,完整实现pickle支持。

先修正并确认my_array的实现

首先注意你的my_array里用了xrange,这是Python2的语法,Python3里要换成range,先修正一下:

import ctypes as ct
import pickle

class my_array(ct.Structure):
    _fields_ = [("_data", ct.POINTER(ct.c_uint32)), ("_size", ct.c_size_t)]
    
    def __init__(self, data):
        # 构建ctypes数组并赋值
        self._data = (ct.c_uint32 * len(data))()
        for i in range(len(data)):
            self._data[i] = data[i]
        self._size = len(data)
    
    def __reduce__(self):
        # 把指针指向的数据提取成Python列表
        data = [self._data[j] for j in range(self._size)]
        # 返回构造函数和对应的参数,pickle会用这个重建对象
        return (my_array, (data,))

实现my_struct的Pickle支持

假设你的my_struct字段是包含一个my_array类型的numbs(如果有其他字段,思路完全一致),我们同样通过__reduce__来拆解和重建对象:

class my_struct(ct.Structure):
    _fields_ = [("numbs", my_array)]
    
    def __init__(self, numbs_data):
        # 初始化时直接传入Python列表,内部自动构建my_array
        self.numbs = my_array(numbs_data)
    
    def __reduce__(self):
        # 提取my_struct里的可序列化核心数据:这里就是numbs对应的Python列表
        # 其实因为my_array已经实现了__reduce__,也可以直接传self.numbs,但提取底层数据更直观
        numbs_data = [self.numbs._data[j] for j in range(self.numbs._size)]
        # 返回构造函数和参数,pickle会用这个重建my_struct实例
        return (my_struct, (numbs_data,))

测试序列化和反序列化

现在来验证一下是否能正常工作:

# 创建测试对象
test_struct = my_struct([1, 2, 3, 4, 5])

# 序列化到字节流
pickled_data = pickle.dumps(test_struct)

# 反序列化重建对象
loaded_struct = pickle.loads(pickled_data)

# 验证数据一致性
print("原始数据:", [test_struct.numbs._data[i] for i in range(test_struct.numbs._size)])
print("反序列化后数据:", [loaded_struct.numbs._data[i] for i in range(loaded_struct.numbs._size)])

关键要点总结

  • __reduce__是pickle序列化的核心,它告诉pickle如何将复杂对象拆解成可序列化的原生Python类型,以及如何用这些数据重建对象
  • 对于ctypes指针,绝对不能直接序列化指针本身(指针是内存地址,反序列化后毫无意义),必须提取指针指向的实际数据,转换成列表、元组等原生类型
  • 如果my_struct有多个字段,只要每个字段都能被pickle序列化(要么是原生类型,要么自己实现了__reduce__),就可以在__reduce__里把所有字段的数据提取出来,作为构造函数的参数返回

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:28:55