Я пытаюсь собрать модуль Python в C ++, используя pybind11.У меня есть следующий код:
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/numpy.h>
namespace py = pybind11;
struct ContainerElement
{
uint8_t i;
double d;
double d2;
};
class Container
{
private:
std::vector<uint8_t> ints;
std::vector<double> doubles;
std::vector<double> doubles2;
public:
std::vector<uint8_t>& getInts() { return ints; }
std::vector<double>& getDoubles() { return doubles; }
std::vector<double>& getDoubles2() { return doubles2; }
void addElement(ContainerElement element)
{
ints.emplace_back(element.i);
doubles.emplace_back(element.d);
doubles2.emplace_back(element.d2);
}
};
void fillContainer(Container& container)
{
for (int i = 0; i < 1e6; ++i)
{
container.addElement({(uint8_t)i, (double)i,(double)i });
}
}
PYBIND11_MODULE(containerInterface, m) {
py::class_<Container>(m, "Container")
.def(py::init<>())
.def("getInts", [](Container& container)
{
return py::array_t<uint8_t>(
{ container.getInts().size() },
{ sizeof(uint8_t) },
container.getInts().data());
})
.def("getDoubles", [](Container& container)
{
return py::array_t<double>(
{ container.getDoubles().size() },
{ sizeof(double) },
container.getDoubles().data());
})
.def("getDoubles2", [](Container& container)
{
return py::array_t<double>(
{ container.getDoubles2().size() },
{ sizeof(double) },
container.getDoubles2().data());
});
m.def("fillContainer", &fillContainer);
}
Когда я вызываю этот код на python:
import containerInterface
container = containerInterface.Container()
containerInterface.fillContainer(container)
i = container.getInts()
d = container.getDoubles()
d2 = container.getDoubles2()
Это работает, однако, когда я проверяю использование памяти программой (используя psutil.Process(os.getpid()).memory_info().rss
) кажется, что я делаю копию, когда я вызываю функции getInts, getDoubles
и getDoubles2
.Есть ли способ избежать этого?
Я пытался использовать np.array(container.getInts(), copy=False)
, но он все равно делает копию.Также я попытался использовать py::buffer_protocol()
для класса Container, как упомянуто здесь: https://pybind11.readthedocs.io/en/stable/advanced/pycpp/numpy.html.Однако я могу сделать это только для вектора Ints или векторов Doubles, но не для всех одновременно.
PYBIND11_MODULE(containerInterface, m) {
py::class_<Container>(m, "Container", py::buffer_protocol())
.def(py::init<>())
.def("getInts", &Container::getInts)
.def("getDoubles", &Container::getDoubles)
.def_buffer([](Container& container) -> py::buffer_info {
return py::buffer_info(
container.getInts().data(),
sizeof(uint8_t),
py::format_descriptor<uint8_t>::format(),
1,
{ container.getInts().size() },
{ sizeof(uint8_t) * container.getInts().size() }
);
});
m.def("fillContainer", &fillContainer);
Тогда я могу использовать i = np.array(container, copy=False)
, без копирования.Однако, как я уже сказал, он работает только для вектора Ints
.