代码之家  ›  专栏  ›  技术社区  ›  Leonardo

IronPyton ctypes联合失败,原因是“SystemError:对象引用未设置为对象的实例。”

  •  0
  • Leonardo  · 技术社区  · 6 年前

    in this answer . 但它失败了 SystemError: Object reference not set to an instance of an object 在那条线上 flags.asbyte = 0xc

    我还试图指出CPython标准lib作为建议 in this message

    import sys
    
    sys.path.append("C:/Python27/DLLs")
    
    import ctypes
    c_uint8 = ctypes.c_uint8
    
    class Flags_bits(ctypes.LittleEndianStructure):
        _fields_ = [
                ("logout", c_uint8, 1),
                ("userswitch", c_uint8, 1),
                ("suspend", c_uint8, 1),
                ("idle", c_uint8, 1),
            ]
    
    class Flags(ctypes.Union):
        _fields_ = [("b", Flags_bits),
                    ("asbyte", c_uint8)]
    
    flags = Flags()
    flags.asbyte = 0xc
    
    print(flags.b.idle)
    print(flags.b.suspend)
    print(flags.b.userswitch)
    print(flags.b.logout)
    

    An example of ctypes on IronPython? 可能很有趣,但公认的答案并不能证明是一个例子。

    编辑:我挖了一点进一步和这个代码(灵感) from this unit test

    from ctypes import *
    
    class ANON(Union):
        _fields_ = [("a", c_int),
                    ("b", c_int)]
    
    a = ANON()
    a.a = 5
    

    而这段代码( from this unit test

    from ctypes import *
    
    class X(Structure):
        _fields_ = [("a", c_longlong, 1),
                    ("b", c_longlong, 62),
                    ("c", c_longlong, 1)]
    
    x = X()
    x.a, x.b, x.c = -1, 7, -1
    

    所以这似乎是铁蟒的局限

    谢谢!

    2 回复  |  直到 6 年前
        1
  •  1
  •   Anthony    6 年前

    您应该升级到IronPython的最新版本,因为上周发布了2.7.9。

    http://ironpython.net/

        2
  •  0
  •   Leonardo    6 年前

    ctypes.Union access fails with "SystemError: Object reference not set to an instance of an object."

    现在,我想出了一个非常难看的解决方案,对我来说很有效:

    class __BleCharacteristicFlags(ctypes.LittleEndianStructure):
        """Creates a class to generically represent bitfields.
    
        Note:
            This ONLY supports ctypes.LittleEndianStructure.
            Unfortunately IronPython 2.7.9 does not supports ctypes.Union. We need this workaround
            code to create an illusion of an union.
        """
        @property
        def as_byte(self):
            """Returns an integer that represents the current set flags
            """
            val = 0
            for i, field in enumerate(self._fields_):
                if getattr(self, field[0]) == 1:
                    val += (0x01<<i)
            return val
    
        @as_byte.setter
        def as_byte(self, hex_val):
            """Writes the flags with a single bitfield.
            """
            for i, field in enumerate(self._fields_):
                if( (hex_val&(0x01<<i)) != 0 ):
                    setattr(self, field[0], 1)
                else:
                    setattr(self, field[0], 0)
    
        def __str__(self):
            """Returns a string that represents the current object.
            """
            s = ""
            for i, field in enumerate(self._fields_):
                if getattr(self, field[0]) == 1:
                    if s != "":
                        s += ", "
                    s += field[0]
            return s
    
    class BleCharacteristicPermissions(__BleCharacteristicFlags):
        """Creates a clas to represent the permissions of a GATT characteristic.
    
        Note:
            The flags values are:
                Readable = 0x01,
                Writeable = 0x02,
                ReadEncryptionRequired = 0x04,
                WriteEncryptionRequired = 0x08,
    
        Attributes:
            readable (int): Readable permission flag. If set the characteristic can be read.
            writeable (int): Writeable permission flag. If set the characteristic can be written.
            read_encryption_required (int): Read encryption required permission flag.  If set the
                characteristic can only be read if encryption is enabled.
            write_encryption_required (int): Write encryption required permission flag.  If set the
                characteristic can only be written if encryption is enabled.
            as_byte (int): The flags bit values read as an integer.
        """
        _fields_ = [
                ("readable", ctypes.c_uint8, 1),
                ("writeable", ctypes.c_uint8, 1),
                ("read_encryption_required", ctypes.c_uint8, 1),
                ("write_encryption_required", ctypes.c_uint8, 1),
            ]