-
Hello, Great library, pleasure to use it. I'm currently creating a Python API to a C++ library which has a pattern that like so: .def_static(
"from_ndarray",
[](nb::ndarray<double, nb::device::cpu> &a)
{
int local_m = a.shape(0);
int local_n = a.shape(1);
double *local_tmp = new double[local_m * local_n];
std::copy(a.data(), a.data() + local_m * local_n, local_tmp);
return MatrixObject::from_ndarray(
local_tmp);
}) I am currently copying the ndarray's contents into a raw pointer but if possible, I'd like to avoid that copy operation (it's not too bad, but I'd like to avoid it). The Numpy arrays that are fed into this C++ code will definitely remain valid (non-GC'd) for the lifetime of the returned MatrixObject. The MatrixObject requires that the memory at a.data() remains valid for the lifetime of the MatrixObject. Is there a way to do this without the copy op? I don't know if there's any more information I can provide but I'd be more than happy to provide as much detail as I can. |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 24 replies
-
Two ways to do this: modify your |
Beta Was this translation helpful? Give feedback.
-
The above example is with a m.def(
"matrix_from_ndarray",
[](nb::ndarray<double, nb::device::cpu> a)
{
return MatrixObject::from_ndarray((double *)a.data());
}, nb::keep_alive<0, 1>()); My understanding from the I think this is from the return value policy (https://nanobind.readthedocs.io/en/latest/api_core.html#_CPPv4N8nanobind9rv_policy9automaticE) being automatically set to Still very new to the library and a bit rusty with C++ memory management so I really appreciate the help through this. |
Beta Was this translation helpful? Give feedback.
Two ways to do this: modify your
MatrixObject
to stash thenb::ndarray
somewhere. Or use akeep_alive
call annotation to ensure that the argument (a
) is kept alive at least as long as the return value of the function.