AddressOf and SetBranchAddress with ROOT 6.22 and pyRoot

Dear ROOT team,

while upgrading our pyroot analysis framework from ROOT 6.18 to 6.22 I’ve come across the changed behaviour of ROOT.AddressOf. Reading the docs, I understood that it should be replaced with ROOT addressof.

This causes a problem with TChain.SetBranchAddress when I’m trying to read branches from a flat ntuple using an instance myClass (of a custom class MyClass). In particular,

chain.SetBranchAddress( "met_pt", ROOT.addressof(myClass, "met_pt")) 

fails, because addressof returns an int while SetBranchAddress expects a void pointer.
I’ve tried casting with ctypes.c_void_p which technically runs, but is not functional, i.e., myClass.met_pt is not changed. The same code with ROOT.AddressOf runs successfully in 6.18.

I put a minimal example into this repository which should make it straightforward to reproduce the problem:

It would be nice if somebody could take a look!

Thanks a lot,
Robert

PS: I can not not use TChains - the code is part of a larger framework.


Please read tips for efficient and successful posting and posting code

ROOT Version: 6.22 and 6.18
Platform: slc7
Compiler: gcc700


Dear all,

my colleague Dietrich Liko found a solution which I paste here for reference.
The cast can be done using cppyy.

from cppyy.ll import cast
chain.SetBranchAddress( "met_pt", cast['void*'](ROOT.addressof(myClass, "met_pt"))) 

I updated the example code. It might be useful to others.

I think that’s a bit much assembly for a SetBranchAddress call.
Am I using it as you intended?

Best,
Robert

Hello,

Yes, the basic change is that, in the old PyROOT, AddressOf(o, "field") returned the address of the field as a buffer, while addressof(o, "field"), which is cppyy’s addressof, returns that address as an integer.

Therefore, your solution of casting that integer to a void* so it can be consumed by SetBranchAddress is a good option. This could also be handled in the pythonization of SetBranchAddress (Python-specific behaviour for that method), but it isn’t at the moment.

OK, thank you for the confirmation!

The issue has been mentioned before here, so I agree, it would be
nice to adapt the behaviour in pyroot.

By the way … If I use the old ROOT.AddressOf

chain.SetBranchAddress( "Jet_pt", ROOT.AddressOf(myClass, "Jet_pt"))

I get the strange and uninformative message

TypeError: AddressOf() takes exactly 2 arguments (3 given) 

I could not figure out why this is the case. Do you know?

AddressOf will be deprecated, it still has the old behaviour (returning a buffer) but does not support fields of objects. I suggest just using addressof instead.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.