2016-10-25 2 views
1

je dois redimensionner dynamiquement un champ de structure ctypes:Redimensionner une structure de ctypes

from ctypes import * 

class a(Structure): 
    _fields_ = [('first', c_ubyte*10), ('second', c_ubyte*20)] 

Maintenant, disons que je dois « second » pour être 100 octets au lieu de 20. J'ai essayé les éléments suivants:

class b(a): 
    _fields_ = [('second', c_ubyte*100)] 

ce qui semble fonctionner:

b.second 
<Field type=c_ubyte_Array_100, ofs=30, size=100> 

le problème est que tout ce qu'il a fait est ajouté le tableau de l'élément 100 à la fin de b:

sizeof(b) #want this to be 110 
130 

c = b() 
addressof(c.second) - addressof(c) #want this to be 10 
30 

Alors, comment puis-je allonger le membre « second » de b sans complètement redéfinir comme une classe sans rapport avec un.

En outre, des solutions telles que le redimensionnement ne fonctionnent pas:

c = a() 
resize(c.second, 100) 
ValueError: Memory cannot be resized because this object doesn't own it 

Répondre

0

Il n'y a pas exactement un moyen simple de faire cela comme ctypes Les structures sont faites pour être assez statique (pour correspondre à leurs homologues c-). Quoi qu'il en soit, vous pouvez sous-classe ctypes.Structure et faire quelque chose comme ceci en fonction de cette classe:

def getUpdated(self, fieldName, fieldType): 
    fieldsCopy = self._fields_ 
    found = False 
    for idx, itm in enumerate(fieldsCopy): 
     # find a matching field name 

     i = list(itm) # can't modify a tuple 
     if i[0] == fieldName: 
      i[1] = fieldType 
      fieldsCopy[idx] = tuple(i) # update the type with the new one 
      found = True 
      break # end the loop 

    if not found: # fieldName wasn't in the field 
     return False 

    class TmpStructure(Structure): 
     ''' we made a new structure type based off the original ''' 
     _pack_ = self._pack_ 
     _fields_ = fieldsCopy 

    return TmpStructure # return the type, though we could probably 
         # pass the values if needed and make a new instance 
         # of the new 

`

Fondamentalement, nous revenions un nouveau type avec un type de champ modifié. Cela pourrait être modifié pour gérer également les champs de bits, l'héritage Structure et/ou renvoyer des instances au lieu des types. Bien que cela devrait être suffisant pour vous aider à démarrer.