Il boost::python::object
fornisce un'interfaccia generalizzata per oggetti Python. Per costruirne uno da PyObject*
, è necessario innanzitutto creare uno boost::python::handle<>
, che è essenzialmente un puntatore intelligente progettato per gestire oggetti Python conteggiati di riferimento (PyObject*
o tipi derivati). Uno spesso usa handle<>
tra il confine tra il codice di livello superiore di Boost.Python e l'API Python/C.
namespace python = boost::python;
PyObject* py_object = get_py_object();
python::handle<> handle(py_object);
boost::python object(handle);
Si noti che il handle
condivideranno la proprietà del PyObject*
, e durante la distruzione, si riduce il conteggio dei riferimenti sul PyObject
essa gestisce. Pertanto, durante la costruzione, è importante specificare se handle<>
deve aumentare o meno il conteggio dei riferimenti di PyObject*
.
Se PyObject
ha già avuto il suo conteggio di riferimento aumentato, quindi utilizzare:
namespace python = boost::python;
PyObject* py_object = ...;
python::handle<> handle(py_object);
python::object object(handle);
Se PyObject
non ha avuto il conteggio di riferimento aumentato, e la maniglia deve farlo, quindi utilizzare la funzione borrowed()
durante la costruzione:
namespace python = boost::python;
PyObject* py_object = ...;
python::handle<> handle(python::borrowed(py_object));
python::object object(handle);
Ecco un esempio completo demonstrating costruzione di un boost::python::object
da un PyObject*
:
#include <vector>
#include <boost/python.hpp>
// Mocks...
enum { NPY_FLOAT };
typedef int npy_intp;
PyObject* PyArray_SimpleNewFromData(int, npy_intp*, int, void*)
{
return PyString_FromString("hello world");
}
boost::python::object build_day(int year, int day)
{
const int HEIGHT = 5;
const int WIDTH = 5;
std::vector<std::vector<float> > array(
WIDTH, std::vector<float>(HEIGHT));
npy_intp dims[2] = {WIDTH, HEIGHT};
namespace python = boost::python;
PyObject* arr = PyArray_SimpleNewFromData(2, dims, NPY_FLOAT, &array);
python::handle<> handle(arr);
return python::object(handle);
}
BOOST_PYTHON_MODULE(example)
{
namespace python = boost::python;
python::def("build_day", &build_day, python::args("year", "day"));
}
utilizzo interattivo:
>>> import example
>>> day = example.build_day(1, 2);
>>> assert(day)
Si noti che per creare un esempio completo minimal, nell'esempio di cui sopra ha una deriso PyArray_SimpleNewFromData()
che restituisce semplicemente stringa di Python. È importante consultare la documentazione per determinare se il numero PyObject*
è preso in prestito o meno e se vi sono dei requisiti di durata tra l'oggetto e i relativi argomenti. Nel caso di PyArray_SimpleNewFromData()
, restituita PyObject*
:
- ha già il conteggio dei riferimenti aumentato
- la durata della memoria sottostante fornito alla matrice deve essere almeno finché il restituito
PyObject
. La funzione build_day()
nella domanda originale non soddisfa questo requisito.