I have a c++ class that
- stores two pointers to the data of two numpy arrays as members (
m_ptrA
,m_ptrB
) - exposes a function to initialize the pointers (
initPtrs
) - exposes a function that operates on the pointers (
doSomethingWithPtrs
)
class Foo
{
public:
void initPtrs( py::array_t<int32_t , py::array::c_style> pyAryA,
py::array_t<float32_t, py::array::c_style> pyAryB
)
{
m_ptrA = (int32_t*) pyAryA.request().ptr;
m_ptrB = (float32_t*) pyAryB.request().ptr;
}
void doSomethingWithPtrs()
{
std::cout << m_ptrB[0] << std::endl; //Crashes sometimes here: Pointer m_ptrB is not valid.
}
private:
int32_t* m_ptrA;
float32_t* m_ptrB;
};
I tried to bind the class and its functions to python using pybind11:
PYBIND11_MODULE(bar,m)
{
py::class_<Foo>(m,"Foo")
.def(py::init<>())
.def( "init_ptrs" , &Foo::initPtrs, py::keep_alive<1,2>(), py::keep_alive<1,3>() )
.def( "do_something_with_ptrs" , &Foo::doSomethingWithPtrs );
}
However, when calling do_something_with_ptrs
after init_ptrs
, the following program crashes sometimes, since the pointer m_ptrB
is invalid:
def test( aryA, torchTensorB ):
my_foo = bar.Foo()
my_foo.init_ptrs( aryA, torchTensorB.numpy() * 3840 )
my_foo.do_something_with_ptrs()
aryA
is a numpy array of type int32.
pyTensorB
is a pytorch tensor of type torch.float32.
I'm pretty new to python/pybind. Any help would be appreciated. In particular, I'm not sure if I understood the py::keep_alive
statements correctly.
IMHO the issue lies somewhere else. I suspect that you are using an uninitialized pointer or going out of bounds.
Without being provided a minimal reproduceable code, I tried to come up with something on my own. I am leaving the sources below for reference. During my testing, everything worked as expected on Windows (with MSVC and Clang). Modifying the array elements in Python showed up in the C++ code. Reassigning the variables in Python and calling the garbage collector manually did not invalidate the C++ class. When removing
keep_alive
(and multiplying the arrays with2
atinit_ptrs
), I also managed to see the same memory being reassigned to the newly initialized array.Sources
test.py
foo.cpp
setup.py
(based on CMake example)CMakeLists.txt