2015-07-17 19 views
5

Sto provando a creare un modulo Python in C++ che trasforma un vettore 2D in un array Numpy 2D. Cosa non è corretto qui - presumibilmente ci sono alcune trasformazioni necessarie per potenziare un oggetto python da PyObject *?Python * per potenziare :: python :: object

boost::python::object build_day(int year, int day) { 

    PyObject* arr; 
    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}; 
    arr = PyArray_SimpleNewFromData(2, dims, NPY_FLOAT, &array); 

    return arr; 
} 

BOOST_PYTHON_MODULE(sumpar) { 
    using namespace boost::python; 
    def("build_day", build_day, args("year", "day")); 
} 

risposta

4

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.
0

Il mio suggerimento è quello di utilizzare le variabili e gli oggetti forniti da boost :: python, quindi se si vuole restituire un array per il pitone dovrebbe può essere che sarebbe una buona idea di utilizzare un boost :: pitone :: dict, qualcosa di simile ...

boost::python::dict arr; 

int i = 0; 
for (auto &item: array) { 
    arr[i] = item; 
    ++i; 
} 

return arr;