редактировать буфер структуры Ctypes - PullRequest
1 голос
/ 19 октября 2019

У меня есть структура Ctypes, которую нужно редактировать стандартным способом [setattr (структура, значение)], которую легко реализовать, но мне также нужно иметь возможность редактировать необработанный буфер, так как я хочу бытьвозможность назначить определенный бит значению (например, бит 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

Я знаю, что это возможносделать example_struct [2] = 0x2b, выполнив огромный_arr [смещение + 2] = 0х2b, но моя программа сложнее, чем в этом примере, и огромный_арр определен (и остается) в основном файле, а пример_структура передается в качестве параметрадругая функция в другом файле, так что огромный_арр находится вне области видимости. Есть ли способ изменить n-й бит exmaple_struct?

Еще одна вещь, которую стоит отметить, эта программа написана на Python 2.7, но даже решение на python3 приветствуется

Спасибозаранее за вашу помощь (и я, безусловно, отмечу лучший ответ для любой доброй души, которая может решить эту проблему)

1 Ответ

1 голос
/ 19 октября 2019

Листинг [Python 3.Docs]: ctypes - библиотека сторонних функций для Python .

В нескольких местах вопроса вы использовали термин " bit ", но вы, вероятно, имели в виду" байт "(поскольку бит может иметь значение только 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\StackOverflow\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.
...