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

Python3中from_buffer_copy转ctypes Structure失败:缓冲区过小原因及解决

问题原因与解决方法

为什么结构体被对齐到28或32字节?

有两个核心原因:

  1. c_ulong的平台差异性:c_ulong的大小依赖系统位数——32位系统下是4字节,64位系统下是8字节。你的IP结构体中src和dst使用c_ulong,在64位系统中这两个字段各占8字节,直接让结构体总大小从理论上的20字节变成28字节(前面字段累计12 + 8*2 = 28)。如果未设置正确的打包规则,编译器还会为对齐更大的字段自动填充字节,最终可能达到32字节。
  2. 错误的打包设置:ctypes中_pack_属性需要设置为整数(表示按多少字节对齐),而非布尔值True。_pack_ = True不会生效,结构体依然遵循默认对齐规则,产生额外填充字节。

如何禁用对齐并让结构体大小为20字节?

修改两点即可:

  1. 替换c_ulong为固定4字节类型:IP地址是32位(4字节),用c_uint32代替c_ulong,确保在任何平台下都是4字节大小。
  2. 正确设置打包规则:将_pack_ = 1,强制结构体按1字节对齐,禁用任何自动填充。

修改后的代码如下:

import ctypes
from ctypes import c_ubyte, c_ushort, c_uint32

class IP(ctypes.Structure):
    _pack_ = 1  # 按1字节对齐,禁用填充
    _fields_ = [
        ("_ihl",            c_ubyte, 4),
        ("version",         c_ubyte, 4),
        ("tos",             c_ubyte),
        ("len",             c_ushort),
        ("id",              c_ushort),
        ("offset",          c_ushort),
        ("ttl",             c_ubyte),
        ("protocol_num",    c_ubyte),
        ("sum",             c_ushort),
        ("src",             c_uint32),  # 用固定4字节类型替代c_ulong
        ("dst",             c_uint32)
    ]
    
    def __new__(self, socket_buffer=None):
        return self.from_buffer_copy(socket_buffer)

修改后结构体大小会严格等于20字节,使用IP(raw_buffer[0:20])创建实例就不会报错了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 18:05:25