编辑 Ctypes 结构的缓冲区
edit the buffer of a Ctypes structure
我有一个 Ctypes 结构,它需要以标准方式 [setattr(structure,value)] 进行编辑,这很容易实现,但我还需要能够编辑原始缓冲区,因为我想要能够将某个位分配给一个值(例如位 25 = 0xd5)
我该怎么做?
非常简化的示例代码,如果有帮助的话
import ctypes as *
#ctypes array with ~250,000 c_uint32 elements
huge_arr = (c_uint32*250,000)(*range(250,000)) # Fill with dummy data for this example
class Example(Structure):
_pack_ = 1
_fields_ = [
("a", c_uint16),
("b", c_uint16, 14),
("c", c_uint16, 2),
("d", c_uint32, 24),
("e", c_uint32, 8),
("f", c_uint16),
("g", c_uint16)
]
offset = 123456
example_struct = Example.from_buffer(huge_arr, offset)
# Ideally, I'd like to be able to set bits in example_struct. for example, example_struct[2] = 0x2b
我知道可以通过 huge_arr[offset+2] = 0x2b 来实现 example_struct[2] = 0x2b,但是我的程序比这个例子更复杂,并且 huge_arr 在主文件中定义(并保留),而 example_struct 作为参数传输到不同文件中的另一个函数,因此 huge_arr 超出范围。有没有办法改变exmaple_struct的第n位?
还有一点要注意,这个程序是用 Python 2.7 编写的,但即使是 python3 解决方案也会受到赞赏
预先感谢您的帮助(我肯定会为任何能够解决此问题的好心人标记最佳答案)
清单[Python 3.Docs]: ctypes - A foreign function library for Python。
你在问题中的几个地方使用了术语“位”,但你可能意味着“byte”(因为一个位只能有一个值0或1).
为了实现您的目标,您可以将结构包装在联合中。
code00.py:
#!/usr/bin/env python3
import sys
import ctypes as ct
class ExampleStruct(ct.Structure):
_pack_ = 1
_fields_ = [
("a", ct.c_uint16),
("b", ct.c_uint16, 14),
("c", ct.c_uint16, 2),
("d", ct.c_uint32, 24),
("e", ct.c_uint32, 8), # @TODO - cfati: Why not c_uint8 ???
("f", ct.c_uint16),
("g", ct.c_uint16),
("test_field", ct.c_uint8), # One byte field would make the example more eloquent
]
class Example(ct.Union):
_anonymous_ = ["struct"]
_fields_ = [
("struct", ExampleStruct),
("raw", ct.c_ubyte * ct.sizeof(ExampleStruct)),
]
def main():
huge_arr_size = 250000
huge_arr = (ct.c_uint32 * huge_arr_size)(*range(huge_arr_size))
arr_offset = 123456
example = Example.from_buffer(huge_arr, arr_offset)
print("example.test_field: {0:d}".format(example.test_field))
test_field_offset = Example.test_field.offset
example.raw[test_field_offset] = 123
print("example.test_field: {0:d}".format(example.test_field))
if __name__ == "__main__":
print("Python {0:s} {1:d}bit on {2:s}\n".format(" ".join(item.strip() for item in sys.version.split("\n")), 64 if sys.maxsize > 0x100000000 else 32, sys.platform))
main()
print("\nDone.")
输出:
[cfati@CFATI-5510-0:e:\Work\Dev\Whosebug\q058460001]> "e:\Work\Dev\VEnvs\py_064_03.07.03_test0\Scripts\python.exe" code00.py
Python 3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 22:22:05) [MSC v.1916 64 bit (AMD64)] 64bit on win32
example.test_field: 147
example.test_field: 123
Done.
我有一个 Ctypes 结构,它需要以标准方式 [setattr(structure,value)] 进行编辑,这很容易实现,但我还需要能够编辑原始缓冲区,因为我想要能够将某个位分配给一个值(例如位 25 = 0xd5) 我该怎么做?
非常简化的示例代码,如果有帮助的话
import ctypes as *
#ctypes array with ~250,000 c_uint32 elements
huge_arr = (c_uint32*250,000)(*range(250,000)) # Fill with dummy data for this example
class Example(Structure):
_pack_ = 1
_fields_ = [
("a", c_uint16),
("b", c_uint16, 14),
("c", c_uint16, 2),
("d", c_uint32, 24),
("e", c_uint32, 8),
("f", c_uint16),
("g", c_uint16)
]
offset = 123456
example_struct = Example.from_buffer(huge_arr, offset)
# Ideally, I'd like to be able to set bits in example_struct. for example, example_struct[2] = 0x2b
我知道可以通过 huge_arr[offset+2] = 0x2b 来实现 example_struct[2] = 0x2b,但是我的程序比这个例子更复杂,并且 huge_arr 在主文件中定义(并保留),而 example_struct 作为参数传输到不同文件中的另一个函数,因此 huge_arr 超出范围。有没有办法改变exmaple_struct的第n位?
还有一点要注意,这个程序是用 Python 2.7 编写的,但即使是 python3 解决方案也会受到赞赏
预先感谢您的帮助(我肯定会为任何能够解决此问题的好心人标记最佳答案)
清单[Python 3.Docs]: ctypes - A foreign function library for Python。
你在问题中的几个地方使用了术语“位”,但你可能意味着“byte”(因为一个位只能有一个值0或1).
为了实现您的目标,您可以将结构包装在联合中。
code00.py:
#!/usr/bin/env python3
import sys
import ctypes as ct
class ExampleStruct(ct.Structure):
_pack_ = 1
_fields_ = [
("a", ct.c_uint16),
("b", ct.c_uint16, 14),
("c", ct.c_uint16, 2),
("d", ct.c_uint32, 24),
("e", ct.c_uint32, 8), # @TODO - cfati: Why not c_uint8 ???
("f", ct.c_uint16),
("g", ct.c_uint16),
("test_field", ct.c_uint8), # One byte field would make the example more eloquent
]
class Example(ct.Union):
_anonymous_ = ["struct"]
_fields_ = [
("struct", ExampleStruct),
("raw", ct.c_ubyte * ct.sizeof(ExampleStruct)),
]
def main():
huge_arr_size = 250000
huge_arr = (ct.c_uint32 * huge_arr_size)(*range(huge_arr_size))
arr_offset = 123456
example = Example.from_buffer(huge_arr, arr_offset)
print("example.test_field: {0:d}".format(example.test_field))
test_field_offset = Example.test_field.offset
example.raw[test_field_offset] = 123
print("example.test_field: {0:d}".format(example.test_field))
if __name__ == "__main__":
print("Python {0:s} {1:d}bit on {2:s}\n".format(" ".join(item.strip() for item in sys.version.split("\n")), 64 if sys.maxsize > 0x100000000 else 32, sys.platform))
main()
print("\nDone.")
输出:
[cfati@CFATI-5510-0:e:\Work\Dev\Whosebug\q058460001]> "e:\Work\Dev\VEnvs\py_064_03.07.03_test0\Scripts\python.exe" code00.py Python 3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 22:22:05) [MSC v.1916 64 bit (AMD64)] 64bit on win32 example.test_field: 147 example.test_field: 123 Done.