Die boost::python::object
bietet eine verallgemeinerte Schnittstelle zu Python-Objekte. Um einen aus einem PyObject*
zu konstruieren, muss man zuerst einen boost::python::handle<>
konstruieren, der im Wesentlichen ein Smart-Pointer ist, der entworfen wurde, um Referenz-gezählte Python-Objekte zu verwalten (PyObject*
oder abgeleitete Typen). Häufig verwendet man handle<>
zwischen der Grenze zwischen Boost.Pythons Code auf höherer Ebene und der Python/C-API.
namespace python = boost::python;
PyObject* py_object = get_py_object();
python::handle<> handle(py_object);
boost::python object(handle);
Beachten Sie, dass die handle
Eigentum an der PyObject*
teilen, und während der Zerstörung, wird die Referenzzählung auf der PyObject
sie managt verringern. Daher ist es wichtig, bei der Konstruktion anzugeben, ob handle<>
die Referenzzahl von PyObject*
erhöhen muss.
Wenn PyObject
hat bereits seine Referenzzähler erhöht wird, dann verwenden:
namespace python = boost::python;
PyObject* py_object = ...;
python::handle<> handle(py_object);
python::object object(handle);
Wenn PyObject
seine Referenzzähler nicht erhöht hatte, und der Griff muss es tun, dann verwenden Sie die borrowed()
Funktion während der Bauphase:
namespace python = boost::python;
PyObject* py_object = ...;
python::handle<> handle(python::borrowed(py_object));
python::object object(handle);
Hier ist ein komplettes Beispiel demonstrating eineKonstruktionvon einer 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"));
}
Interaktive Nutzung:
>>> import example
>>> day = example.build_day(1, 2);
>>> assert(day)
Beachten Sie, dass ein minimales vollständiges Beispiel das obige Beispiel zu schaffen, hat verspottet PyArray_SimpleNewFromData()
, die einfach Python-String zurückzugibt. Es ist wichtig, die Dokumentation zu Rate zu ziehen, um zu bestimmen, ob die PyObject*
ausgeliehen ist oder nicht, und ob es lebenslange Anforderungen zwischen dem Objekt und seinen Argumenten gibt. Im Fall von PyArray_SimpleNewFromData()
die PyObject*
zurückgegeben:
- hat bereits seine Referenzzählung
- die Lebensdauer des zugrunde liegenden Speichers zu dem Array bereitgestellt erhöht muss mindestens so lang wie die zurück
PyObject
sein. Die build_day()
Funktion in der ursprünglichen Frage erfüllt diese Anforderung nicht.