2013-03-06 7 views
3

Этот вопрос относится к предыдущему вопросу, который я задал. А именно: this one, если кому-то интересно. В основном, я хочу показать массив C на Python, используя Py_buffer, завернутый в объект memoryview. Я получил его для работы с использованием PyBuffer_FillInfo (work = я могу манипулировать данными в Python и записывать его в stdout в C), но если я попытаюсь свернуть собственный буфер, я получу segfault после функция C вернется.Использование Py_buffer и PyMemoryView_FromBuffer с различными товарами

Мне нужно, чтобы создать свой собственный буфер, поскольку PyBuffer_FillInfo предполагает, что формат голец, что делает itemsize поле 1. Мне нужно, чтобы быть в состоянии обеспечить детали размером 1, 2, 4 и 8.

Некоторые код , это рабочий пример:

Py_buffer *buf = (Py_buffer *) malloc(sizeof(*buf)); 
int r = PyBuffer_FillInfo(buf, NULL, malloc(sizeof(char) * 4), 4, 0, PyBUF_CONTIG); 
PyObject *mv = PyMemoryView_FromBuffer(buf); 
//Pack the memoryview object into an argument list and call the Python function 
for (blah) 
    printf("%c\n", *buf->buf++); //this prints the values i set in the Python function 

Глядя на реализацию PyBuffer_FillInfo, которая на самом деле просто, я свернул свою собственную функцию, чтобы быть в состоянии предоставить пользовательские itemsizes:

//buffer creation function 
Py_buffer *getReadWriteBuffer(int nitems, int itemsize, char *fmt) { 
    Py_buffer *buf = (Py_buffer *) malloc(sizeof(*buf)); 
    buf->obj = NULL 
    buf->buf = malloc(nitems * itemsize); 
    buf->len = nitems * itemsize; 
    buf->readonly = 0; 
    buf->itemsize = itemsize; 
    buf->format = fmt; 
    buf->ndim = 1; 
    buf->shape = NULL; 
    buf->strides = NULL; 
    buf->suboffsets = NULL; 
    buf->internal = NULL; 
    return buf; 
} 

Как я использовать:

Py_buffer *buf = getReadWriteBuffer(32, 2, "h"); 
PyObject *mv = PyMemoryView_FromBuffer(buf); 
// pack the memoryview into an argument list and call the Python function as before 

for (blah) 
    printf("%d\n", *buf->buf); //this prints all zeroes even though i modify the array in Python 

return 0; 
//the segfault happens somewhere after here 

В результате использования моего собственного объекта буфера является после выдаст ошибку сегментации функции C возвращается. Я действительно не понимаю, почему это происходит вообще. Любая помощь будет оценена по достоинству.

EDIT Согласно this question, который мне не удалось найти раньше, itemsize> 1 может даже не поддерживаться на всех. Это делает этот вопрос еще более интересным. Возможно, я мог бы использовать PyBuffer_FillInfo с достаточно большим блоком памяти для хранения того, что я хочу (например, 32 C). В этом случае возникает вопрос о том, как назначать поплавки Python объекту memoryview в функции Python. Вопросы вопросы.

+0

Произошла утечка памяти, если 'Py_buffer' malloc'ed. Использовать стек, назначенный 'Py_buffer' – dyomas

ответ

2

Итак, в отсутствие ответов я решил сделать другой подход, чем тот, который я изначально планировал. Оставляя это здесь, если кто-то другой попадает в ту же самую ловушку.

В принципе, вместо создания буфера (или bytearray, equiv.) В C и передачи его Python для внутреннего пользователя, который должен быть изменен. Я просто немного изменил код, чтобы пользователь возвращал bytearray (или любой тип, поддерживающий интерфейс буфера) из функции обратного вызова Python. Таким образом, мне не нужно даже беспокоиться о размерах элементов, поскольку в моем случае весь код C с возвращенным объектом должен извлечь свой буфер и скопировать его в другой буфер с помощью простого memcpy.

Код:

PYGILSTATE_ACQUIRE; //a macro i made 
PyObject *result = PyEval_CallObject(python_callback, NULL); 
if (!PyObject_CheckBuffer(result)) 
    ; //raise exception 

Py_buffer *view = (Py_buffer *) malloc(sizeof(*view)); 
int error = PyObject_GetBuffer(result, view, PyBUF_SIMPLE); 
if (error) 
    ; //raise exception 

memcpy(my_other_buffer, view->buf, view->len); 

PyBuffer_Release(view); 
Py_DECREF(result); 
PYGILSTATE_RELEASE; //another macro 

Я надеюсь, что это поможет кому-то.

 Смежные вопросы

  • Нет связанных вопросов^_^