Hi Wenzel,
I'm trying to construct a py::array from a bare pointer without copying data.
In #27 you mentioned that
... the memory is copied during the construction of array. The way to avoid this is by creating the array first and then writing the data directly to it ...
Could you please elaborate a bit on how to do this?
Also, it seems to me a simple alternative would be to optionally skip the PyArray_NewCopy call in the py::array constructor, something like
template <typename Type> array(size_t size, const Type *ptr, bool copy = true) {
...
if (copy && ptr && tmp)
tmp = object(api.PyArray_NewCopy_(tmp.ptr(), -1 /* any order */), false);
...
}
I tried this and it seems to work just fine. Am I missing something here?
Thanks!
To make it truly safe (reference counting and all), you also need to inform PyArray about the object which owns the buffer. A way of directly doing this sort of stuff with pybind11 is in the works (#308) but may still take a bit.
@wjakob @yangle This is on my next-to-do list for sure, but will take a bit of effort to do properly and will require a separate PR.
Hello @wjakob, can you please explain how the merged #308 resolved this?
I'v spent almost a day to figure out how make pybind11 array without copying the data, but still could not find the solution...
Can you please help?
Ok guys, after reading lots of SO articles, lots of pybind issues, PRs and discussions and after reading the code I figured it out:
I need to pass _any_ valid pybind object as the base parameter to an array ctor, and then pybind won't copy...
HUH! 馃槃
Now my code looks like this:
void addInput(std::shared_ptr<const MyFancyMatrix> packet)
{
// When a valid object is passed as 'base', it tells pybind not to take ownership of the data,
// because 'base' will own it. In fact 'packet' will own it, but - psss! - , we don't tell it to
// pybind... Alos note that ANY valid object is good for this purpose, so I chose "str"...
py::str dummyDataOwner;
py::array input{getNumpyDTypeFromElementType(packet->elementType()), packet->shape(),
packet->strides(), packet->data(), dummyDataOwner};
assert(!input.owndata()); // if fires, s.g. is not OK with ownership (probably matrix data was copied)
// ...
}
Awesome hacky undocumented stuff... 馃榿 馃専
it will be great if pybind11 could provide more documents on handling numpy arrays
Most helpful comment
it will be great if pybind11 could provide more documents on handling numpy arrays