IronPyton ctypes联合失败,并显示“ SystemError:对象引用未设置为对象实例”。

时间:2018-10-15 22:10:21

标签: ctypes ironpython

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

我还尝试通过添加CPython 2.7.8路径指向建议的in this message指向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的局限性

谢谢!

2 个答案:

答案 0 :(得分:1)

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

http://ironpython.net/

答案 1 :(得分:0)

此问题被视为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),
        ]