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。
这个问题被认为是 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),
]
我正在尝试使用 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。
这个问题被认为是 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),
]