ctypes.c_char 与 ctypes.c_ubyte

问题描述 投票:0回答:1

我可以通过两种方式定义包含字节数组的结构,作为 c_char 数组或 c_ubyte 数组:

import ctypes
                                 
class Char(ctypes.Structure):                 
    _fields_ = [('value',ctypes.c_char * 12)] 
                                              
class Byte(ctypes.Structure):                 
    _fields_ = [('value',ctypes.c_ubyte * 12)]

我可以非常直接地为 Char() 实例赋值:

>>> ci = Char()        
>>> ci.value = b'Hello world'
>>> print(ci.value)
b'Hello world'     

但是如果我尝试对 Byte() 实例进行类似的赋值,我会得到一个 TypeError:

>>> bi = Byte()                                         
>>> bi.value = b'Hello world'                           
Traceback (most recent call last):                      
  File "<stdin>", line 1, in <module>                   
TypeError: expected c_ubyte_Array_12 instance, got bytes

C 并没有真正的字节类型,所以我可以使用 c_char,但我觉得使用 ctypes c_ubyte 更清楚地揭示了我的意图,这就是我尝试的原因。

是否有充分的理由不允许将 Python 字节分配给 ctypes.c_ubyte 数组?这对我来说似乎很奇怪,所以我担心我对 c_ubyte 有一些不理解的地方。

python python-3.x ctypes
1个回答
0
投票

c_char
在结构中具有特殊的默认处理,将其视为以 null 结尾的字符串。
c_ubyte
(和
c_byte
,签名版本)不要这样做。 您仍然可以使用字节字符串分配给它们,但需要使用切片并分配与切片大小相同的字节字符串:

import ctypes

class Char(ctypes.Structure):
    _fields_ = [('value',ctypes.c_char * 12)]

    def __repr__(self):
        return f'Char({self.value})'

class Byte(ctypes.Structure):
    _fields_ = [('value', ctypes.c_ubyte * 12)]

    def __repr__(self):
        return f'Byte({bytes(self.value)})'

c = Char()
print(c.value)  # converted to byte string. doesn't show nulls
c.value = b'hello'
print(c)  # b'hello'
c.value = b'123456789abc'
print(c)  # b'123456789abc'
try:
    c.value = b'123456789abcd'  # error: too long
except ValueError as e:
    print(e)

b = Byte()
print(b.value)  # still an array
b.value[:5] = b'hello'  # assign 5-byte string to 5-byte slice.
print(b)  # shows nulls
b.value[:] = b'123456789abc'  # array size is 12, string exactly fits, no nulls
print(b)
try:
    b.value[:] = b'123456789ab'  # array size is 12, byte string is 11, error: too short
except ValueError as e:
    print(e)

输出:

b''
Char(b'hello')
Char(b'123456789abc')
bytes too long (13, maximum length 12)
<__main__.c_ubyte_Array_12 object at 0x0000022D5EC2F850>
Byte(b'hello\x00\x00\x00\x00\x00\x00\x00')
Byte(b'123456789abc')
Can only assign sequence of same size
© www.soinside.com 2019 - 2024. All rights reserved.