Как вернуть допустимый объект из python в C , пока этот объект был сконструирован с использованием handle?

#c #python #boost-python

#c #python #boost-python

Вопрос:

Я хочу выделить буфер в C и предоставить его python в качестве объекта memoryview. Для этого я предоставляю эту функцию с помощью boost::python :

 object* Allocator()
{
    void* buff = my_alloc_function(char, size);
    Py_buffer pybuffer;
    int res = PyBuffer_FillInfo(amp;pybuffer, 0, buff, size, false, PyBUF_CONTIG);
    if (res == -1)
        return NULL;
    handle<> obj_handle(borrowed(PyMemoryView_FromBuffer(amp;pybuffer)));
    object obj = object(obj_handle);
    return amp;obj;
}
  

Я также хочу иметь возможность предоставлять деструктор C , вызываемый python, как только счетчик ref объекта python становится равным нулю.
Мне удалось вызвать мой деструктор с помощью python и получить возвращаемый указатель с помощью Allocator() в качестве параметра моего деструктора.

Далее, текущая функция C , вызываемая python :

 void Destructor()(object* pyMemoryView_object) const 
{
    Py_buffer* py_buffer = PyMemoryView_GET_BUFFER(pyMemoryView_object);
    my_free_function(py_buffer->buf);
    PyBuffer_Release(py_buffer);
}
  

Кажется, все идет хорошо, пока не вызван деструктор…

Проблема, с которой я сталкиваюсь, заключается в том, что Py_buffer py_buffer имеет допустимый адрес, но содержит удаленные элементы (как показано как 0xcccccccccc в отладчике).

Мой первый вопрос :

Как вернуть допустимый объект Py_buffer в C из python, пока этот объект был создан с использованием handle<> и обернут в объект python ?

Мой второй вопрос будет :

Должен ли я вызывать PyBuffer_Release(), поскольку он может быть вызван python после вызова Destructor() ?

Спасибо за всю вашу помощь!

Ответ №1:

Мне удалось заставить его работать.

Вот код двух функций (без политики возврата при их предоставлении):

 PyObject* Allocator()
{
    void* buff = my_alloc_function(char, size);
    Py_buffer pybuffer;
    int res = PyBuffer_FillInfo(amp;pybuffer, 0, buff, size, false, PyBUF_CONTIG);
    if (res == -1)
        return NULL;
    return PyMemoryView_FromBuffer(amp;pybuffer);
}

void Destructor()(object pyMemoryView_object) const 
{
    Py_buffer* py_buffer = PyMemoryView_GET_BUFFER(pyMemoryView_object.ptr());
    my_free_function(py_buffer->buf);
    PyBuffer_Release(py_buffer);
}
  

Важный момент, который я усвоил, заключается в том, что при возврате объекта в python используйте PyObject* .

При получении объекта из python используйте object .

Ответ №2:

Глядя на ваш пример, я буду удивлен, если возврат адреса объекта, выделенного в стеке, является приемлемым. Просто вернуть объект по значению?

Комментарии:

1. Я получаю те же результаты, если помещаю эти элементы в статическую область видимости.