#!/usr/bin/env python # coding: utf-8 # # Invoke C++ from Python without bindings thanks to ROOT #
# With [ROOT](http://root.cern.ch), it's possible to use interactively C++ libraries from Python without the need to write bindings. The C++ entities known to the interpreter are exposed to Python transparently. # Let's dive into an example. # # The following sources include a class, a function and a template. # # ## Header File # In[1]: get_ipython().run_cell_magic('python', '', 'code=\'\'\'\n#include \n#include \n\n/// A trivial class\nclass A {\npublic:\n A();\n ~A();\n};\n\n/// A trivial function\nint CountCharacters(const std::string s);\n\n/// A trivial template\ntemplate\nclass B {\npublic:\n B()\n {\n std::cout << "The typeid name of the template argument is " << typeid(T).name() << std::endl;\n }\n};\n\'\'\'\nwith open(\'myLibrary.h\',\'w\') as f_out:\n f_out.write(code)\n') # ## Implementation # In[2]: get_ipython().run_cell_magic('python', '', 'code=\'\'\'\n#include "myLibrary.h" \nA::A()\n{\n std::cout << "This is the constructor of A" << std::endl;\n}\n\nA::~A()\n{\n std::cout << "This is the destructor of A" << std::endl;\n}\n\nint CountCharacters(const std::string s)\n{\n return s.size();\n}\n\'\'\'\nwith open(\'myLibrary.cc\',\'w\') as f_out:\n f_out.write(code)\n') # ## Creation of the Library # It's trivial to create a shared object starting from the sources above: # In[3]: get_ipython().run_cell_magic('bash', '', 'g++ -o libmyLibrary.so -shared -fPIC myLibrary.cc \n') # In[4]: get_ipython().run_cell_magic('bash', '', 'ls *so\n') # So far, so good. Now we'll see how easy it is to use this library from within Python thanks to [ROOT](http://root.cern.ch). # ## Interactivity without bindings # In order to interact with the C++ entities contained in the library, we need to carry out to tasks: # 1. We need to make known to the interpreter the *interfaces*. Concretely this means including one or more headers. # 2. We need to make accessible to the interpreter the implementations of such C++ entities. Concretely this means loading the library. # # In code: # In[5]: import ROOT ROOT.gInterpreter.ProcessLine('#include "myLibrary.h"') ROOT.gSystem.Load("./libmyLibrary.so") # That's it! We can now start exploring the content of the library. If you are wondering what a return code equal to 0 means, ROOT is telling us that the loading of the library happened without problems! # In[6]: a = ROOT.A() # In[7]: del a # In[8]: b_doublePtr = ROOT.B("double*")() # Notice how the "impedence mismatch" generated by the concept of templates is ironed out in this case. The template parameter is specified as string in parentheses. # In[9]: ROOT.CountCharacters("This interactivity without bindings is really impressive.") # ## Interactivity within C++ # Interactive usage of C++ libraries is possible also in C++ mode. In this case, no wrapper is interposed between the statement written by the user and the call - ABI compatibility is leveraged. For example: # In[10]: get_ipython().run_cell_magic('cpp', '', 'A a;\n')