-
Notifications
You must be signed in to change notification settings - Fork 211
V1.63 boost::python::numpy ndarray from_data method 'own' parameter usage #97
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
If you mean the |
I've read that documentation but it isn't very clear what own should be or the side effects if 'ownership' is messed up. So I thought I would ask a high level question to see if the flag OWNDATA: False on the Python side would contribute to corrupt data. |
In case some one is interested... I'll have to strip out a test case that's small enough (it will take a bit of time that I don't currently have) but if this is useful for someone, I'm attaching some of the relevant methods: struct record { BOOST_PYTHON_MODULE(_distancerank) {
}
} npy::ndarray CdistanceRank::NCosineRank(npy::ndarray& pyfeaturematrix, py::list& pyidvector, npy::ndarray& pyrefvector) {
} Environment: |
Thanks ! I'll likewise try to look into this. If you pass |
I am experiencing the exact same issue. Is there already a fix for this? Or does someone know a workaround for it? |
I wonder what it means for the array to own its own data. Does it mean that if the array is passed to python, then I do not need to manage the data associated with the array in C++, and the array and the associated data will be correctly deleted without memory leaks when it goes out of scope in python? |
I have the cure for what ails you! I will make a post on stack overflow asking the question and then answering it, but for now, here is a straightforward way to return an ndarray to python whose data has been allocated in C++, and it will own it's data (in the sense that it will be deallocated when nothing references the python object). And furthermore, it doesn't use the numpy C api, only Boost.Numpy. This is pretty much exactly the same as the basic example usage of
Export the function with boost and use it like this:
And it will produce the following output
Notice that during the first iteration, the PyCapsule_Destructor is not called, it's when the second iteration happens, when we assign a new thing to the variable |
If take the exact same code but we don't do the Put the capsule back in and then we're back to having the data owned by the array. Also this works but I wanted to interact only through the boost.Numpy objects if possible
|
This is a demonstration that passing
And corresponding output from running the python script
|
@PhilippeCarphin Thank you so much!! I solved my problem thanks to you! namespace py = boost::python;
namespace np = boost::python::numpy;
template<typename T>
inline void destroyManagerCObject(PyObject* self) {
auto * b = reinterpret_cast<T*>( PyCapsule_GetPointer(self, NULL) );
delete [] b;
}
np::ndarray ConvertMatToNDArray(const cv::Mat& mat) {
py::tuple shape = py::make_tuple(mat.rows, mat.cols, mat.channels());
py::make_tuple(mat.rows, mat.cols, mat.channels());
np::dtype dt = np::dtype::get_builtin<uchar>();
size_t depth = sizeof(uchar);
PyObject *capsule = nullptr;
switch(mat.depth()){
case CV_8U:
capsule = ::PyCapsule_New((void *)mat.data, NULL, (PyCapsule_Destructor)&destroyManagerCObject<uchar>);
break;
case CV_8S:
dt = np::dtype::get_builtin<char>();
depth = sizeof(char);
capsule = ::PyCapsule_New((void *)mat.data, NULL, (PyCapsule_Destructor)&destroyManagerCObject<char>);
break;
case CV_16U:
dt = np::dtype::get_builtin<uint16_t>();
depth = sizeof(uint16_t);
capsule = ::PyCapsule_New((void *)mat.data, NULL, (PyCapsule_Destructor)&destroyManagerCObject<uint16_t>);
break;
case CV_16S:
dt = np::dtype::get_builtin<int16_t>();
depth = sizeof(int16_t);
capsule = ::PyCapsule_New((void *)mat.data, NULL, (PyCapsule_Destructor)&destroyManagerCObject<int16_t>);
break;
default: std::cout << "wrong dtype error" << std::endl; break;
}
py::handle<> h_capsule{capsule};
py::object owner_capsule{h_capsule};
py::tuple stride = py::make_tuple(mat.channels() * mat.cols * depth, mat.channels() * depth, depth);
np::ndarray ndImg = np::from_data(mat.data, dt, shape, stride, owner_capsule);
return ndImg;
} |
Not sure how to use the 'own' parameter.
End result is that on the python side when the ndarray 'flags' are printed, I see:
OWNDATE: False
The returned array on python side is garbled (though works sometimes!).
Data on the C++ side of the ndarray (that is being returned to Python) is correct always.
Is this related to the 'own' parameter. Or some other scope issue?
Currently I have 'own' set to: py::object()
The text was updated successfully, but these errors were encountered: