I wrote some shared libraries in C++ that I am trying to use in python, using
ROOT.gSystem.Load()
I can get everything to run fine, but at one point I have a function
int getEntry(const LUTKey&k, const LUTEntry*& e) const;
which returns an int depending on if it failed or not, and sets the pointer “e” to something. python complains that “e” must be initialized beforehand, but I’m not sure how to do this. Any tips and or better ideas on how to use C++ libraries in python? Thanks
Hi,
you are taking a const reference to a pointer and then trying to change the pointer, that doesn’t sound ok.
As a first approximation you might want to remove the const-ness, but I’m not sure how PyROOT supports references to pointers (@etejedor might know).
If everything else fails, you can always change the function signature to take a reference to an ad-hoc type that encapsulates a pointer instead of a reference to pointer.
PyROOT converts both references and pointers in C++ to references in Python. How are you making this call from Python? What are you passing as second parameter of getEntry?
@eguiraud This code works in C++ fine, I intend to be able to change the pointer itself, but not change any of the data that it points to, which I believe is how this should be done.
key = r.LUTKey(event.patternId, event.ccId)
#this code works, and creates the correct class
if lut.getEntry(key, entry):
exit()
#lut is the class which has getEntry as it's member function, the class gets created correctly
If I don’t initial instantiate entry, which gives me an error:
Traceback (most recent call last):
File "makeChi2Plots.py", line 33, in <module>
if lut.getEntry(key, entry):
NameError: name 'entry' is not defined
I tried with an empty constructor
entry = r.LUTEntry()
if lut.getEntry(key, entry):
but get
free(): invalid pointer
Aborted
which I’m guessing has to do with python trying to free the memory, but C++ not allowing it to.
@eguiraud This code works in C++ fine, I intend to be able to change the pointer itself, but not change any of the data that it points to, which I believe is how this should be done.
sorry, I parsed it as LUTEntry* const & e
In the first example as written entry is never initialized so "name entry is not defined" seems kosher.
In the second example with the empty constructor I think you are confusing PyROOT’s lifetime management by creating an object “on the stack” and then passing it to a function that takes it as a pointer.
You can create the entry object as a pointer in a C++ helper function.
This works:
// entry.h
struct Entry {
int v;
};
const Entry *GetPtr()
{
return new Entry{0};
}
void ChangePtr(const Entry *&p)
{
p = new Entry{1};
}
As a more high-level suggestion, since you are writing the C++ code yourself, my personal experience is that adhering to modern C++ practices and preferring value semantics to pointer semantics, designing your types so that they can be passed around as values or references and your interfaces so that they do not deal with raw pointers, not only reduces the amount of issues in the C++ code itself but makes that code more usable from python. Just my two cents