Pass const Long64_t& to C++ class

Hi,

I have a problem passing a reference to a Long64_t between python and C++. In the past I’ve had similar problems with class and Double_t references, solved by searching in this forum, but so far I’ve found no solution for this particular case.

I’ve attached two files that replicate the issue, and closely matches my real use-case. I have a (library) class that takes a const Long64_t&, which I need to increment over time (it actually represents the entry number in a tree), and the C++ must follow these changes (the variable is private/protected, and there’s no set method to change it after the constructor). I’ve tried this in ROOT 5.30/05, where my analysis is run, as well as the more recent 5.32/00. In both cases, I get the same result:

[quote]
Internally stored number: 5
Internally stored number: 5
Python value is 22[/quote]

The result I want is, of course:

[quote]Internally stored number: 5
Internally stored number: 22
Python value is 22[/quote]

The usefunc.py file also includes my other experiments to date, none of which have worked. I’ve also messed around a bit with ROOT.AddressOf and ROOT.AsCObject, but with no joy.

Any suggestions?

I don’t know if this is relevant, but when preparing the example, I hit a different error. Initially, func.C had a function (as the file name implies, taking and modifying a non-const Long64_t&), rather than a class. When I tried to run it, I saw this:

[quote]Traceback (most recent call last):
File “usefunc.py”, line 9, in
ROOT.somefunc(somevalue)
TypeError: void ::somefunc(Long64_t& thing) =>
could not convert argument 1 (‘long’ object has no attribute ‘typecode’)[/quote]

It perhaps has no relevance to my actual problem, but I mention it because I thought it was curious that a C++ function and C++ class would have such different behaviours.

Cheers,
Mike
usefunc.py (194 Bytes)
func.C (259 Bytes)

Mike,

that’s not going to work: there is nothing in the interface that the address will be taken (even in C++, this code is deeply flawed: the const Long64_t& could be the result of a function return, for example). This is also the reason why the behavior is different for your Long64_t& example (the non-const one): from there you could take a pointer, so e.g. passing a buffer is possible.

So, for your const-ref example, you’ll need some structure containing a Long64_t, and add that through a helper. Something like:[code]struct MyLong64 {
Long64_t val;
};

someclass* someclass_create(MyLong64* ml) {
return new someclass(ml->val);
}[/code]
This way, you can create the structure separately and keep it alive as required:[code]somevalue = ROOT.MyLong64()
somevalue.val = 5L

obj = ROOT.someclass_create(somevalue);
obj.show()
somevalue.val += 17
obj.show()
print ‘Python value is’,somevalue.val[/code]
Cheers,
Wim

Hi Wim,

That’s a great suggestion, thanks! The way I’m structuring everything, it’s one-off code anyway, that will be hidden from the end-user analysis code.

Cheers,
Mike