/ / Кой е най-ефективният начин за копиране на външно предоставен буфер в байтове - python, python-2.7, python-3.x, ctypes

Кой е най-ефективният начин за копиране на външен буфер до байтове - python, python-2.7, python-3.x, ctypes

Свързвам се с външна библиотека, използваща ctypes. Тази библиотека връща ми двоичен буфер. Интерфейсът изглежда така:

int getBuff(unsigned char **buf, int *len);

Библиотеката изнася и дистрибутор, така че аз мога да освободя буфера, когато свърша с него, но този аспект не представлява проблем за мен, така че не мисля, че трябва да го покриваме.

В моя ctypes код представлявам buf аргумент като c_void_p, Бих искал да копирам този буфер в един байт обект възможно най-ефективно.

В момента имам:

data = bytes(bytearray(ctypes.cast(buf, ctypes.POINTER(ctypes.c_ubyte*len.value))[0]))

където buf е c_void_p и len е c_int.

Както разбирам, това прави две копия. Веднъж към обектът bytearray, а след това отново към обекта на байта.

Как мога да направя това само с едно копие?

Сегашните ми усилия са съсредоточени върху Python 2, но след време ще трябва да го подкрепя и за Python 3.

Отговори:

6 за отговор № 1

Очевидно можете да нарязвате ctypes указател. Не c_void_p, c_char_p, или c_wchar_p, но POINTER типове работа. За POINTER(c_char), нарязвайки го bytes:

data = ctypes.POINTER(ctypes.c_char).from_buffer(buf)[:len.value]

Благодарение на eryksun за това. Също така не е ясно защо buf е c_void_p вместо да е вече POINTER(c_char), (За POINTER(c_char), кодът ще бъде справедлив buf[:len.value].)


За получаване bytes от общия обект, който поддържа протокола на буфера, memoryview(...).tobytes() включва по-малко копие от bytes(bytearray(...)):

data = memoryview(ctypes.cast(buf, ctypes.POINTER(ctypes.c_ubyte*len.value))[0]).tobytes()

Това е съвместимо с Python 2 и Python 3.


Имайте предвид, че buf тук трябва да има указател към буфера, а не указател към указател към буфера. getBuff отнема указател към показалеца (толкова вероятно byref(buf)).