import ROOT

"""
Explanation: Using ROOT to bind Python and C++
What is PyROOT?

PyROOT is the name of the Python bindings offered by ROOT
All the ROOT C++ functions and classes are accessible from Python via PyROOT
Python façade, C++ performance
But PyROOT is not just for ROOT!
It can also call into user-defined C++ code

How does PyROOT work?

PyROOT is a special type of bindings, since it's automatic and dynamic
No static wrapper generation
Dynamic python proxies are created for C++ entities
Lazy class/variable lookup
Powered by cppyy, the ROOT type system and Cling
Reflection information
JIT C++ compilation and execution
And on top of the automatic bindings: pythonizations
To make the use of C++ from Python simpler, more pythonic

Using ROOT from Python
To start working with PyROOT, we need to import the ROOT module.
End of explanation
"""


h = ROOT.TH1F("my_histo", "Example histogram", 100, -4, 4)

"""
Explanation: The ROOT Python module is the entry point for all the ROOT C++ functionality.
For example, we can create a histogram with ROOT using the TH1F C++ class from Python:
End of explanation
"""


ROOT.gInterpreter.ProcessLine("""
double add(double a, double b) {
    return a + b;
}
""")

"""
Explanation: Calling user-defined C++ code via PyROOT
We've seen how PyROOT allows to access all the functions and classes that the ROOT C++ libraries define.
In addition, it is possible to make PyROOT call into user-defined C++. For example, it is possible to declare a C++ function, as it is done below by passing its code as a string argument of the ProcessLine function:
End of explanation
"""


ROOT.add(3.14, 100)

"""
Explanation: and use it right away from Python:
End of explanation
"""


ROOT.gInterpreter.ProcessLine("void print_integer(int i) { std::cout << i << std::endl; }")

ROOT.print_integer(7)

"""
Explanation: What about code in C++ libraries?
In the example we just saw, the user-defined C++ code is contained in strings in our program, but PyROOT can also load and call into C++ libraries. This enables you to write high-performance C++, compile it and use it from Python.
More information can be found here.
Type conversions
When calling C++ from Python via PyROOT, there needs to be a conversion between the Python arguments we pass and the C++ arguments that the C++ side expects. PyROOT takes care of such conversion automatically, for example from Python integer to C++ integer:
End of explanation
"""


ROOT.print_integer([]) # fails with TypeError

"""
Explanation: Of course not every conversion is allowed!
End of explanation
"""


ROOT.gInterpreter.ProcessLine("""
void print_vector(const std::vector<std::string> &v) {
    for (auto &s : v) {
        std::cout << s << std::endl;
    }
}
""")

ROOT.print_vector(['Two', 'Words'])

"""
Explanation: An example of a useful allowed conversion is Python list to std::vector:
End of explanation
"""


