Python ctypes 深度复制结构

问题描述 投票:0回答:1

我不太习惯 python ctypes,如果这是一个天真的问题,很抱歉。我正在尝试复制一个结构,这是我的代码:

from ctypes import *

class Group(Structure):
    _fields_ = [
        ("ChSize", c_uint32*9),
        ("DataChannel", POINTER(c_float)*9),
        ("TriggerTimeLag", c_uint32),
        ("StartIndexCell", c_uint16)]
    
    def deepcopy(self):
        copy = Group()
        for n_channel in range(9):
            data_buffer = c_float*self.ChSize[n_channel]
            memmove(
                addressof(data_buffer),
                self.DataChannel[n_channel], 
                self.ChSize[n_channel]*sizeof(c_float),
            )
            copy.ChSize[n_channel] = self.ChSize[n_channel]
            copy.DataChannel[n_channel] = addressof(data_buffer)
            copy.TriggerTimeLag = self.TriggerTimeLag
            copy.StartIndexCell = self.StartIndexCell
        return copy

但是,当我尝试使用它时,我发现

TypeError: invalid type

创建

Group
对象的全新副本的正确方法是什么?

python ctypes deep-copy
1个回答
0
投票

假设九个大小代表九个DataChannel指针各自指向的每个浮点数组的长度:

import ctypes as ct

class Group(ct.Structure):
    _fields_ = (('ChSize', ct.c_uint32 * 9),
                ('DataChannel', ct.POINTER(ct.c_float) * 9),
                ('TriggerTimeLag', ct.c_uint32),
                ('StartIndexCell', ct.c_uint16))

    def __repr__(self):
        s = f'Group(ChSize={self.ChSize[:]}, TriggerTimeLag={self.TriggerTimeLag}, StartIndexCell={self.StartIndexCell})\n'
        for i in range(9):
            s += f'  DataChannel[{i}] = {self.DataChannel[i][:self.ChSize[i]]}\n'
        return s

    def deepcopy(self):
        copy = Group.from_buffer_copy(self)  # make a shallow copy
        # Note: at this point the data channels point to the original group
        for i, (size, channel) in enumerate(zip(self.ChSize, self.DataChannel)):  # iterate channels
            data = (ct.c_float * size)(*channel[:size]) # make a copy of the data for a channel
            copy.DataChannel[i] = ct.cast(data, ct.POINTER(ct.c_float))  # store a pointer to that data in the copy
        return copy

# Validation

# Create, initialize and display a group
group = Group()
group.ChSize[:] = [1,2,3,4,5,6,7,8,9]
for i, size in enumerate(group.ChSize):
    data = (ct.c_float * size)(*[1.5 * n for n in range(size)])
    group.DataChannel[i] = ct.cast(data, ct.POINTER(ct.c_float))
group.TriggerTimeLag = 123
group.StartIndexCell = 456
print(group)

copy = group.deepcopy()  # make a copy

# Zero out the channels of the original
group.ChSize[:] = [0] * 9
group.DataChannel[:] = [None] * 9

print(group)  # display zeroed-out group
print(copy)   # display copy

输出:

Group(ChSize=[1, 2, 3, 4, 5, 6, 7, 8, 9], TriggerTimeLag=123, StartIndexCell=456)
  DataChannel[0] = [0.0]
  DataChannel[1] = [0.0, 1.5]
  DataChannel[2] = [0.0, 1.5, 3.0]
  DataChannel[3] = [0.0, 1.5, 3.0, 4.5]
  DataChannel[4] = [0.0, 1.5, 3.0, 4.5, 6.0]
  DataChannel[5] = [0.0, 1.5, 3.0, 4.5, 6.0, 7.5]
  DataChannel[6] = [0.0, 1.5, 3.0, 4.5, 6.0, 7.5, 9.0]
  DataChannel[7] = [0.0, 1.5, 3.0, 4.5, 6.0, 7.5, 9.0, 10.5]
  DataChannel[8] = [0.0, 1.5, 3.0, 4.5, 6.0, 7.5, 9.0, 10.5, 12.0]

Group(ChSize=[0, 0, 0, 0, 0, 0, 0, 0, 0], TriggerTimeLag=123, StartIndexCell=456)
  DataChannel[0] = []
  DataChannel[1] = []
  DataChannel[2] = []
  DataChannel[3] = []
  DataChannel[4] = []
  DataChannel[5] = []
  DataChannel[6] = []
  DataChannel[7] = []
  DataChannel[8] = []

Group(ChSize=[1, 2, 3, 4, 5, 6, 7, 8, 9], TriggerTimeLag=123, StartIndexCell=456)
  DataChannel[0] = [0.0]
  DataChannel[1] = [0.0, 1.5]
  DataChannel[2] = [0.0, 1.5, 3.0]
  DataChannel[3] = [0.0, 1.5, 3.0, 4.5]
  DataChannel[4] = [0.0, 1.5, 3.0, 4.5, 6.0]
  DataChannel[5] = [0.0, 1.5, 3.0, 4.5, 6.0, 7.5]
  DataChannel[6] = [0.0, 1.5, 3.0, 4.5, 6.0, 7.5, 9.0]
  DataChannel[7] = [0.0, 1.5, 3.0, 4.5, 6.0, 7.5, 9.0, 10.5]
  DataChannel[8] = [0.0, 1.5, 3.0, 4.5, 6.0, 7.5, 9.0, 10.5, 12.0]

© www.soinside.com 2019 - 2024. All rights reserved.