如何将BitString转换为ctypes字节数组?

4

我刚开始接触BitString和ctypes,我已经将部分二进制文件存储在startdata中,这是一个BitArray类。

> print(startdata)
0x0000000109f0000000010605ffff

现在,我需要将这些数据原样传递给一个接受unsigned char *参数的C函数,因此我首先尝试做如下操作:
buf = (c_ubyte * len(startdata))()

最终要做到这个:

buf_ptr = cast(pointer(buf), POINTER(c_ubyte))

这个方案是可行的,但是我该如何将startdata的字节数据分配给我刚刚创建的数组/缓冲区呢?
这种方法不可行:
> buf = (c_ubyte * len(startdata))(*startdata.bytes)
TypeError: an integer is required
1个回答

3

以下是可能的解决方案(请注意,我使用的是python 3):

import ctypes

def bitarray_to_ctypes_byte_buffer(data):
    """Convert a BitArray instance to a ctypes array instance"""
    ba = bytearray(data.bytes)
    ba_len = len(ba)
    buffer = (ctypes.c_uint8 * ba_len).from_buffer(ba)
    return buffer

(注意:将bytes实例转换为ctypes字节数组也适用相同的方法,只需在data.bytes中删除.bytes即可。)
然后,您可以使用byref将缓冲区传递给C函数:
byref(buffer)

当我这样做时,它会显示:ValueError: Buffer size too small (786 instead of at least 6288 bytes)。在我的情况下,len(startdata)是6288。你知道为什么会发生这种情况吗?我正在使用带有bytes函数的bytearray(startdata.bytes) - slhck
那个完美地解决了!也许你可以编辑一下你的答案,使它们能够与BitArray实例一起使用? :) 感谢你的帮助。 - slhck
2
我忘了提到使用byref传递Array是不必要的。C数组总是通过引用传递的。否则,您需要byref来传递引用,例如对于简单类型(_SimpleCData),指针(_Pointer_CFuncPtr),结构或联合体。因此,如果代码需要通用地处理所有ctypes缓冲区,则在数组上使用byref是可以的。 - Eryk Sun
@eryksun,我没有看到你的评论,最好@-ping我 :) 我需要使用的函数签名需要使用unsigned char *,而且我已经很多年没有使用C++了。 Ctypes文档说unsigned char对应于c_ubyte。这就是为什么我选择了它。 - slhck
@slhck,那是一组相同的字节。使用c_char数组和c_char_p可能更方便。例如,c_char数组有一个value属性,使得赋值(字节)字符串变得容易,并且在用作结果类型或作为结构字段访问时会自动转换为(字节)字符串。 - Eryk Sun
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接