Is it possible to construct an instance of a standard ROOT class in PyROOT starting from a raw pointer? I’m writing a Python wrapper for a C++ library using module ctypes. With a simple example, in the C interface I have a code like
A couple of drawbacks is that this way I wouldn’t have control on what parts of the library are exposed and the library couldn’t use a newer version of the C++ standard than the one with which ROOT had been built.
Anyway, I’m just curious whether the lower-level approach I outlined in the first post is possible. I thought that PyROOT might be doing something like that under the hood.
From signature it looks exactly what I had in mind, but when I try to use it from Python, I get a segfault. Will probably try to play with it more later.
Thank you @wlav. ROOT.BindObject does the job for me. Do you know if the ownership of the object is transferred to Python? I’m not sure I fully understand the code of BindCppObjectNoCast, which seems to be called under the hood.
I suspect I did something stupid there. I tried with
ROOT.TPython.ObjectProxy_FromVoidPtr(ch, 'TH1D')
but this gives a TypeError because the first argument cannot be converted. So I tried feeding ctypes.c_void_p(ch) instead, which resulted in the crash. Here is the stack trace:
===========================================================
#0 0x00000036e78ac82e in waitpid () from /lib64/libc.so.6
#1 0x00000036e783e479 in do_system () from /lib64/libc.so.6
#2 0x00007fdeae532431 in TUnixSystem::StackTrace() () at /gridsoft/ipnls/root/v6.10.04_source/core/unix/src/TUnixSystem.cxx:2118
#3 0x00007fdeae53480c in TUnixSystem::DispatchSignals(ESignals) () at /gridsoft/ipnls/root/v6.10.04_source/core/unix/src/TUnixSystem.cxx:3643
#4 <signal handler called>
#5 0x00007fdeada83498 in vtable for TAxis () from /gridsoft/ipnls/root/v6.10.04/lib/libHist.so
#6 0x00007fdeb561f027 in ?? ()
#7 0x00007fdeb561f010 in ?? ()
#8 0x0000000000000000 in ?? ()
===========================================================
PyROOT has no way to check ownership, but it won’t own that object. You can use ROOT.SetOwnership(cpph, True) to set it, though (in cppyy master, this is all an attribute on the object: __python_owns__, so it can be both read and written).
Yes, ‘ctypes.c_void_p(ch)’ will not work: the address is not extracted in the converter. Instead, the python object is passed through the void*.