IronPyton ctypes union failing with "SystemError: Object reference not set to an instance of an object."

IronPyton ctypes union failing with "SystemError: Object reference not set to an instance of an object."

我正在尝试使用 IronPython 2.7.9 中的 ctypes 创建位域 class。我正在尝试示例 in this answer。但是当访问联盟成员时,flags.asbyte = 0xc 行出现 SystemError: Object reference not set to an instance of an object 失败。

我还尝试按照建议 in this message 通过添加 CPython 2.7.8 路径指向 CPython stdlib,但这也不起作用。

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

所以这似乎是 IronPython 的限制

谢谢!

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

http://ironpython.net/

这个问题被认为是 IronPython 2.7.9 上的错误 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),
        ]