Calling from_buffer_copy in the constructor of inherited ctypes.Structure class

时光总嘲笑我的痴心妄想 提交于 2021-02-07 04:01:01

问题


I have the following piece of code:

class MyStruct(ctypes.Structure):
      _fields_= [('id', ctypes.uint),
                 ('perm', ctypes.uint)]

When the class is defined, i'm able to copy data from buffer directly on my fields. Eg:

ms = MyStruct.from_buffer_copy("\xAA\xAA\xAA\xAA\x11\x11\x11\x11")
print ms.id, ms.perm

Everythings works fine, here id will be 0xAAAAAAAA and perm equals to 0x11111111.

Now, i tried to do the same thing during the instantiation, with the following code:

class MyStruct(ctypes.Structure):
      _fields_= [('id', ctypes.uint),
                 ('perm', ctypes.uint)]
      def __init__(self):
          super(MyStruct, self).__init__()
          self.from_buffer_copy("\xAA\xAA\xAA\xAA\x11\x11\x11\x11")

ms = MyStruct()
print ms.id, ms.perm

But my code raises an error with the following statement :

AttributeError: 'MyStruct' object has no attribute 'from_buffer_copy'

After some research i found that from_buffer_copy is a ctypes._CData method. On the documentation we can read that _CData class is non-public class.

So here my problem. I would like to use from_buffer_copy in the constructor but it looks 'not callable' at this moment. Could you help me ?

Thanks in advance for your reply Regards

PS: I don't want to use the style super(MyStruct,self).__init__(id=0x44444444,perm=0x11111111) because on my real code there are a lot of arguments on my fields variable.


回答1:


The problem is that from_buffer_copy creates new Structure instance from the given buffer. When you use it inside __init__, the Structure has already been created and thus there would be no way to make use of from_buffer_copy (and this is why it is only available as a class method, not an instance method).

An easy solution is just to keep using MyStruct.from_buffer_copy as you have or write another factory function to suit your needs. If you insist on using using MyStruct(buffer), then you can use __new__for this purpose since it is called before the instance has been created:

import ctypes
class MyStruct(ctypes.Structure):
    _fields_= [('id', ctypes.c_uint),('perm', ctypes.c_uint)]
    def __new__(cls, buf):
        return cls.from_buffer_copy(buf)

    def __init__(self, data):
        pass  ## data is already present in class

ms = MyStruct("\xAA\xAA\xAA\xAA\x11\x11\x11\x11")
print ms.id, ms.perm


来源:https://stackoverflow.com/questions/11485496/calling-from-buffer-copy-in-the-constructor-of-inherited-ctypes-structure-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!