Использование ctypes Python для получения буфера чисел с плавающей запятой из общей библиотеки в строку Python
-
22-08-2019 - |
Вопрос
Я пытаюсь использовать ctypes Python для использования этих двух функций C из общей библиотеки:
bool decompress_rgb(unsigned char *data, long dataLen, int scale)
float* getRgbBuffer()
Первая функция работает нормально.Я могу это определить, поместив некоторый отладочный код в общую библиотеку и проверив входные данные.
Проблема в том, чтобы вывести данные.Буфер RGB представляет собой указатель на число с плавающей запятой (очевидно), и этот указатель остается постоянным в течение всего срока службы приложения.Поэтому всякий раз, когда я хочу распаковать изображение, я вызываю decompress_rgb
а затем нужно посмотреть, что находится в месте, указанном getRgbBuffer
.Я знаю, что размер буфера равен (720 * 288 * sizeof(float)), так что, думаю, это где-то должно сыграть свою роль.
Нет никаких c_float_p
типа, поэтому я решил попробовать это:
getRgbBuffer.restype = c_char_p
Затем я делаю:
ptr = getRgbBuffer()
print "ptr is ", ptr
который просто выводит:
ptr = 3078746120
Я предполагаю, что это фактический адрес, а не содержимое, но даже если бы я успешно разыменовал указатель и получил содержимое, это был бы только первый символ.
Как я могу получить содержимое всего буфера в строку Python?
Редактировать: Пришлось поменять:
getRgbBuffer.restype = c_char_p
к
getRgbBuffer.restype = c_void_p
но тогда ответ BastardSaint сработал.
Решение
Не полностью проверено, но думаю, что-то в этом роде:
buffer_size = 720 * 288 * ctypes.sizeof(ctypes.c_float)
rgb_buffer = ctypes.create_string_buffer(buffer_size)
ctypes.memmove(rgb_buffer, getRgbBuffer(), buffer_size)
Ключ – это ctypes.memmove()
функция.Из документация ctypes:
memmove(dst, src, count)
То же, что и стандартная библиотечная функция memmove C:копииcount
байты изsrc
кdst
.dst
иsrc
должны быть целыми числами или экземплярами ctypes, которые можно преобразовать в указатели.
После запуска приведенного выше фрагмента rgb_buffer.value
вернет содержимое до первого '\0'
.Чтобы получить все байты в виде строки Python, вы можете разрезать все это: buffer_contents = rgb_buffer[:]
.
Другие советы
Прошло много времени с тех пор, как я использовал ctypes, и у меня нет чего-то, что возвращало бы «двойной *», достаточно удобного, чтобы проверить это, но если вам нужен c_float_p:
c_float_p = ctypes.POINTER(ctypes.c_float)
Читая ответ BastardSaint, вам просто нужны необработанные данные, но я не был уверен, делаете ли вы это в качестве обходного пути отсутствия c_float_p.