Logo ROOT  
Reference Guide
TPython.cxx
Go to the documentation of this file.
1 // Author: Enric Tejedor CERN 08/2019
2 // Original PyROOT code by Wim Lavrijsen, LBL
3 //
4 // /*************************************************************************
5 // * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. *
6 // * All rights reserved. *
7 // * *
8 // * For the licensing terms see $ROOTSYS/LICENSE. *
9 // * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 // *************************************************************************/
11 
12 // Bindings
13 // CPyCppyy.h must be go first, since it includes Python.h, which must be
14 // included before any standard header
15 #include "CPyCppyy.h"
16 #include "PyStrings.h"
17 #include "TPython.h"
18 #include "CPPInstance.h"
19 #include "CPPOverload.h"
20 #include "ProxyWrappers.h"
21 #include "TPyClassGenerator.h"
22 
23 // ROOT
24 #include "TROOT.h"
25 #include "TClassRef.h"
26 #include "TObject.h"
27 
28 // Standard
29 #include <stdio.h>
30 #include <Riostream.h>
31 #include <string>
32 
33 /// \class TPython
34 /// Accessing the Python interpreter from C++.
35 ///
36 /// The TPython class allows for access to python objects from Cling. The current
37 /// functionality is only basic: ROOT objects and builtin types can freely cross
38 /// the boundary between the two interpreters, python objects can be instantiated
39 /// and their methods can be called. All other cross-coding is based on strings
40 /// that are run on the python interpreter.
41 ///
42 /// Examples:
43 ///
44 /// ~~~{.cpp}
45 /// $ root -l
46 /// // Execute a string of python code.
47 /// root [0] TPython::Exec( "print(\'Hello World!\')" );
48 /// Hello World!
49 ///
50 /// // Create a TBrowser on the python side, and transfer it back and forth.
51 /// // Note the required explicit (void*) cast!
52 /// root [1] TBrowser* b = (void*)TPython::Eval( "ROOT.TBrowser()" );
53 /// root [2] TPython::Bind( b, "b" );
54 /// root [3] b == (void*) TPython::Eval( "b" )
55 /// (int)1
56 ///
57 /// // Builtin variables can cross-over by using implicit casts.
58 /// root [4] int i = TPython::Eval( "1 + 1" );
59 /// root [5] i
60 /// (int)2
61 /// ~~~
62 ///
63 /// And with a python file `MyPyClass.py` like this:
64 /// ~~~{.py}
65 /// print 'creating class MyPyClass ... '
66 ///
67 /// class MyPyClass:
68 /// def __init__( self ):
69 /// print 'in MyPyClass.__init__'
70 ///
71 /// def gime( self, what ):
72 /// return what
73 /// ~~~
74 /// one can load a python module, and use the class. Casts are
75 /// necessary as the type information can not be otherwise derived.
76 /// ~~~{.cpp}
77 /// root [6] TPython::LoadMacro( "MyPyClass.py" );
78 /// creating class MyPyClass ...
79 /// root [7] MyPyClass m;
80 /// in MyPyClass.__init__
81 /// root [8] std::string s = (char*)m.gime( "aap" );
82 /// root [9] s
83 /// (class TString)"aap"
84 /// ~~~
85 /// It is possible to switch between interpreters by calling `TPython::Prompt()`
86 /// on the Cling side, while returning with `^D` (EOF). State is preserved between
87 /// successive switches.
88 ///
89 /// The API part provides (direct) C++ access to the bindings functionality of
90 /// PyROOT. It allows verifying that you deal with a PyROOT python object in the
91 /// first place (CPPInstance_Check for CPPInstance and any derived types, as well
92 /// as CPPInstance_CheckExact for CPPInstance's only); and it allows conversions
93 /// of `void*` to an CPPInstance and vice versa.
94 
95 //- data ---------------------------------------------------------------------
97 static PyObject *gMainDict = 0;
98 
99 namespace CPyCppyy {
100  extern PyObject *gThisModule;
101 }
102 
103 //- static public members ----------------------------------------------------
104 /// Initialization method: setup the python interpreter and load the
105 /// ROOT module.
107 {
108  static Bool_t isInitialized = kFALSE;
109  if (isInitialized)
110  return kTRUE;
111 
112  if (!Py_IsInitialized()) {
113 // this happens if Cling comes in first
114 #if PY_VERSION_HEX < 0x03020000
115  PyEval_InitThreads();
116 #endif
117  Py_Initialize();
118 #if PY_VERSION_HEX >= 0x03020000
119  PyEval_InitThreads();
120 #endif
121 
122  // try again to see if the interpreter is initialized
123  if (!Py_IsInitialized()) {
124  // give up ...
125  std::cerr << "Error: python has not been intialized; returning." << std::endl;
126  return kFALSE;
127  }
128 
129 // set the command line arguments on python's sys.argv
130 #if PY_VERSION_HEX < 0x03000000
131  char *argv[] = {const_cast<char *>("root")};
132 #else
133  wchar_t *argv[] = {const_cast<wchar_t *>(L"root")};
134 #endif
135  PySys_SetArgv(sizeof(argv) / sizeof(argv[0]), argv);
136 
137  // force loading of the ROOT module
138  PyRun_SimpleString(const_cast<char *>("import ROOT"));
139  }
140 
141  if (!gMainDict) {
142  // retrieve the main dictionary
143  gMainDict = PyModule_GetDict(PyImport_AddModule(const_cast<char *>("__main__")));
144  Py_INCREF(gMainDict);
145  }
146 
147  // python side class construction, managed by ROOT
148  gROOT->AddClassGenerator(new TPyClassGenerator);
149 
150  // declare success ...
151  isInitialized = kTRUE;
152  return kTRUE;
153 }
154 
155 ////////////////////////////////////////////////////////////////////////////////
156 /// Import the named python module and create Cling equivalents for its classes
157 /// and methods.
158 
159 Bool_t TPython::Import(const char *mod_name)
160 {
161  // setup
162  if (!Initialize())
163  return kFALSE;
164 
165  PyObject *mod = PyImport_ImportModule(mod_name);
166  if (!mod) {
167  PyErr_Print();
168  return kFALSE;
169  }
170 
171  // allow finding to prevent creation of a python proxy for the C++ proxy
172  Py_INCREF(mod);
173  PyModule_AddObject(CPyCppyy::gThisModule, mod_name, mod);
174 
175  // force creation of the module as a namespace
176  TClass::GetClass(mod_name, kTRUE);
177 
178  PyObject *dct = PyModule_GetDict(mod);
179 
180  // create Cling classes for all new python classes
181  PyObject *values = PyDict_Values(dct);
182  for (int i = 0; i < PyList_GET_SIZE(values); ++i) {
183  PyObject *value = PyList_GET_ITEM(values, i);
184  Py_INCREF(value);
185 
186  // collect classes
187  if (PyClass_Check(value) || PyObject_HasAttr(value, CPyCppyy::PyStrings::gBases)) {
188  // get full class name (including module)
189  PyObject *pyClName = PyObject_GetAttr(value, CPyCppyy::PyStrings::gCppName);
190  if (!pyClName) {
191  pyClName = PyObject_GetAttr(value, CPyCppyy::PyStrings::gName);
192  }
193 
194  if (PyErr_Occurred())
195  PyErr_Clear();
196 
197  // build full, qualified name
198  std::string fullname = mod_name;
199  fullname += ".";
200  fullname += CPyCppyy_PyText_AsString(pyClName);
201 
202  // force class creation (this will eventually call TPyClassGenerator)
203  TClass::GetClass(fullname.c_str(), kTRUE);
204 
205  Py_XDECREF(pyClName);
206  }
207 
208  Py_DECREF(value);
209  }
210 
211  Py_DECREF(values);
212 
213  // TODO: mod "leaks" here
214  if (PyErr_Occurred())
215  return kFALSE;
216  return kTRUE;
217 }
218 
219 ////////////////////////////////////////////////////////////////////////////////
220 /// Execute the give python script as if it were a macro (effectively an
221 /// execfile in __main__), and create Cling equivalents for any newly available
222 /// python classes.
223 
224 void TPython::LoadMacro(const char *name)
225 {
226  // setup
227  if (!Initialize())
228  return;
229 
230  // obtain a reference to look for new classes later
231  PyObject *old = PyDict_Values(gMainDict);
232 
233 // actual execution
234 #if PY_VERSION_HEX < 0x03000000
235  Exec((std::string("execfile(\"") + name + "\")").c_str());
236 #else
237  Exec((std::string("__pyroot_f = open(\"") + name + "\"); "
238  "exec(__pyroot_f.read()); "
239  "__pyroot_f.close(); del __pyroot_f")
240  .c_str());
241 #endif
242 
243  // obtain new __main__ contents
244  PyObject *current = PyDict_Values(gMainDict);
245 
246  // create Cling classes for all new python classes
247  for (int i = 0; i < PyList_GET_SIZE(current); ++i) {
248  PyObject *value = PyList_GET_ITEM(current, i);
249  Py_INCREF(value);
250 
251  if (!PySequence_Contains(old, value)) {
252  // collect classes
253  if (PyClass_Check(value) || PyObject_HasAttr(value, CPyCppyy::PyStrings::gBases)) {
254  // get full class name (including module)
255  PyObject *pyModName = PyObject_GetAttr(value, CPyCppyy::PyStrings::gModule);
256  PyObject *pyClName = PyObject_GetAttr(value, CPyCppyy::PyStrings::gName);
257 
258  if (PyErr_Occurred())
259  PyErr_Clear();
260 
261  // need to check for both exact and derived (differences exist between older and newer
262  // versions of python ... bug?)
263  if ((pyModName && pyClName) &&
264  ((CPyCppyy_PyText_CheckExact(pyModName) && CPyCppyy_PyText_CheckExact(pyClName)) ||
265  (CPyCppyy_PyText_Check(pyModName) && CPyCppyy_PyText_Check(pyClName)))) {
266  // build full, qualified name
267  std::string fullname = CPyCppyy_PyText_AsString(pyModName);
268  fullname += '.';
269  fullname += CPyCppyy_PyText_AsString(pyClName);
270 
271  // force class creation (this will eventually call TPyClassGenerator)
272  TClass::GetClass(fullname.c_str(), kTRUE);
273  }
274 
275  Py_XDECREF(pyClName);
276  Py_XDECREF(pyModName);
277  }
278  }
279 
280  Py_DECREF(value);
281  }
282 
283  Py_DECREF(current);
284  Py_DECREF(old);
285 }
286 
287 ////////////////////////////////////////////////////////////////////////////////
288 /// Execute a python stand-alone script, with argv CLI arguments.
289 ///
290 /// example of use:
291 /// const char* argv[] = { "1", "2", "3" };
292 /// TPython::ExecScript( "test.py", sizeof(argv)/sizeof(argv[0]), argv );
293 
294 void TPython::ExecScript(const char *name, int argc, const char **
295 #if PY_VERSION_HEX < 0x03000000
296  argv
297 #endif
298  )
299 {
300 
301  // setup
302  if (!Initialize())
303  return;
304 
305  // verify arguments
306  if (!name) {
307  std::cerr << "Error: no file name specified." << std::endl;
308  return;
309  }
310 
311  FILE *fp = fopen(name, "r");
312  if (!fp) {
313  std::cerr << "Error: could not open file \"" << name << "\"." << std::endl;
314  return;
315  }
316 
317  // store a copy of the old cli for restoration
318  PyObject *oldargv = PySys_GetObject(const_cast<char *>("argv")); // borrowed
319  if (!oldargv) // e.g. apache
320  PyErr_Clear();
321  else {
322  PyObject *l = PyList_New(PyList_GET_SIZE(oldargv));
323  for (int i = 0; i < PyList_GET_SIZE(oldargv); ++i) {
324  PyObject *item = PyList_GET_ITEM(oldargv, i);
325  Py_INCREF(item);
326  PyList_SET_ITEM(l, i, item); // steals ref
327  }
328  oldargv = l;
329  }
330 
331  // create and set (add progam name) the new command line
332  argc += 1;
333 #if PY_VERSION_HEX < 0x03000000
334  const char **argv2 = new const char *[argc];
335  for (int i = 1; i < argc; ++i)
336  argv2[i] = argv[i - 1];
337  argv2[0] = Py_GetProgramName();
338  PySys_SetArgv(argc, const_cast<char **>(argv2));
339  delete[] argv2;
340 #else
341 // TODO: fix this to work like above ...
342 #endif
343 
344  // actual script execution
345  PyObject *gbl = PyDict_Copy(gMainDict);
346  PyObject *result = // PyRun_FileEx closes fp (b/c of last argument "1")
347  PyRun_FileEx(fp, const_cast<char *>(name), Py_file_input, gbl, gbl, 1);
348  if (!result)
349  PyErr_Print();
350  Py_XDECREF(result);
351  Py_DECREF(gbl);
352 
353  // restore original command line
354  if (oldargv) {
355  PySys_SetObject(const_cast<char *>("argv"), oldargv);
356  Py_DECREF(oldargv);
357  }
358 }
359 
360 ////////////////////////////////////////////////////////////////////////////////
361 /// Execute a python statement (e.g. "import ROOT").
362 
363 Bool_t TPython::Exec(const char *cmd)
364 {
365  // setup
366  if (!Initialize())
367  return kFALSE;
368 
369  // execute the command
370  PyObject *result = PyRun_String(const_cast<char *>(cmd), Py_file_input, gMainDict, gMainDict);
371 
372  // test for error
373  if (result) {
374  Py_DECREF(result);
375  return kTRUE;
376  }
377 
378  PyErr_Print();
379  return kFALSE;
380 }
381 
382 ////////////////////////////////////////////////////////////////////////////////
383 /// Evaluate a python expression (e.g. "ROOT.TBrowser()").
384 ///
385 /// Caution: do not hold on to the return value: either store it in a builtin
386 /// type (implicit casting will work), or in a pointer to a ROOT object (explicit
387 /// casting to a void* is required).
388 
389 const TPyReturn TPython::Eval(const char *expr)
390 {
391  // setup
392  if (!Initialize())
393  return TPyReturn();
394 
395  // evaluate the expression
396  PyObject *result = PyRun_String(const_cast<char *>(expr), Py_eval_input, gMainDict, gMainDict);
397 
398  // report errors as appropriate; return void
399  if (!result) {
400  PyErr_Print();
401  return TPyReturn();
402  }
403 
404  // results that require no convserion
405  if (result == Py_None || CPyCppyy::CPPInstance_Check(result) || PyBytes_Check(result) || PyFloat_Check(result) ||
406  PyLong_Check(result) || PyInt_Check(result))
407  return TPyReturn(result);
408 
409  // explicit conversion for python type required
410  PyObject *pyclass = PyObject_GetAttrString(result, const_cast<char*>("__class__"));
411  if (pyclass != 0) {
412  // retrieve class name and the module in which it resides
413  PyObject *name = PyObject_GetAttr(pyclass, CPyCppyy::PyStrings::gName);
414  PyObject *module = PyObject_GetAttr(pyclass, CPyCppyy::PyStrings::gModule);
415 
416  // concat name
417  std::string qname = std::string(CPyCppyy_PyText_AsString(module)) + '.' + CPyCppyy_PyText_AsString(name);
418  Py_DECREF(module);
419  Py_DECREF(name);
420  Py_DECREF(pyclass);
421 
422  // locate ROOT style class with this name
423  TClass *klass = TClass::GetClass(qname.c_str());
424 
425  // construct general ROOT python object that pretends to be of class 'klass'
426  if (klass != 0)
427  return TPyReturn(result);
428  } else
429  PyErr_Clear();
430 
431  // no conversion, return null pointer object
432  Py_DECREF(result);
433  return TPyReturn();
434 }
435 
436 ////////////////////////////////////////////////////////////////////////////////
437 /// Bind a ROOT object with, at the python side, the name "label".
438 
439 Bool_t TPython::Bind(TObject *object, const char *label)
440 {
441  // check given address and setup
442  if (!(object && Initialize()))
443  return kFALSE;
444 
445  // bind object in the main namespace
446  TClass *klass = object->IsA();
447  if (klass != 0) {
448  PyObject *bound = CPyCppyy::BindCppObject((void *)object, Cppyy::GetScope(klass->GetName()));
449 
450  if (bound) {
451  Bool_t bOk = PyDict_SetItemString(gMainDict, const_cast<char *>(label), bound) == 0;
452  Py_DECREF(bound);
453 
454  return bOk;
455  }
456  }
457 
458  return kFALSE;
459 }
460 
461 ////////////////////////////////////////////////////////////////////////////////
462 /// Enter an interactive python session (exit with ^D). State is preserved
463 /// between successive calls.
464 
466 {
467  // setup
468  if (!Initialize()) {
469  return;
470  }
471 
472  // enter i/o interactive mode
473  PyRun_InteractiveLoop(stdin, const_cast<char *>("\0"));
474 }
475 
476 ////////////////////////////////////////////////////////////////////////////////
477 /// Test whether the type of the given pyobject is of CPPInstance type or any
478 /// derived type.
479 
481 {
482  // setup
483  if (!Initialize())
484  return kFALSE;
485 
486  // detailed walk through inheritance hierarchy
487  return CPyCppyy::CPPInstance_Check(pyobject);
488 }
489 
490 ////////////////////////////////////////////////////////////////////////////////
491 /// Test whether the type of the given pyobject is CPPinstance type.
492 
494 {
495  // setup
496  if (!Initialize())
497  return kFALSE;
498 
499  // direct pointer comparison of type member
500  return CPyCppyy::CPPInstance_CheckExact(pyobject);
501 }
502 
503 ////////////////////////////////////////////////////////////////////////////////
504 /// Test whether the type of the given pyobject is of CPPOverload type or any
505 /// derived type.
506 
508 {
509  // setup
510  if (!Initialize())
511  return kFALSE;
512 
513  // detailed walk through inheritance hierarchy
514  return CPyCppyy::CPPOverload_Check(pyobject);
515 }
516 
517 ////////////////////////////////////////////////////////////////////////////////
518 /// Test whether the type of the given pyobject is CPPOverload type.
519 
521 {
522  // setup
523  if (!Initialize())
524  return kFALSE;
525 
526  // direct pointer comparison of type member
527  return CPyCppyy::CPPOverload_CheckExact(pyobject);
528 }
529 
530 ////////////////////////////////////////////////////////////////////////////////
531 /// Extract the object pointer held by the CPPInstance pyobject.
532 
534 {
535  // setup
536  if (!Initialize())
537  return 0;
538 
539  // check validity of cast
540  if (!CPyCppyy::CPPInstance_Check(pyobject))
541  return 0;
542 
543  // get held object (may be null)
544  return ((CPyCppyy::CPPInstance *)pyobject)->GetObject();
545 }
546 
547 ////////////////////////////////////////////////////////////////////////////////
548 /// Bind the addr to a python object of class defined by classname.
549 
550 PyObject *TPython::CPPInstance_FromVoidPtr(void *addr, const char *classname, Bool_t python_owns)
551 {
552  // setup
553  if (!Initialize())
554  return 0;
555 
556  // perform cast (the call will check TClass and addr, and set python errors)
557  PyObject *pyobject = CPyCppyy::BindCppObjectNoCast(addr, Cppyy::GetScope(classname), false);
558 
559  // give ownership, for ref-counting, to the python side, if so requested
560  if (python_owns && CPyCppyy::CPPInstance_Check(pyobject))
561  ((CPyCppyy::CPPInstance *)pyobject)->PythonOwns();
562 
563  return pyobject;
564 }
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
static Bool_t CPPInstance_CheckExact(PyObject *pyobject)
Test whether the type of the given pyobject is CPPinstance type.
Definition: TPython.cxx:493
static Bool_t CPPInstance_Check(PyObject *pyobject)
Test whether the type of the given pyobject is of CPPInstance type or any derived type...
Definition: TPython.cxx:480
bool CPPInstance_Check(T *object)
Definition: CPPInstance.h:118
static Bool_t Exec(const char *cmd)
Execute a python statement (e.g. "import ROOT").
Definition: TPython.cxx:363
static PyObject * CPPInstance_FromVoidPtr(void *addr, const char *classname, Bool_t python_owns=kFALSE)
Bind the addr to a python object of class defined by classname.
Definition: TPython.cxx:550
static void LoadMacro(const char *name)
Execute the give python script as if it were a macro (effectively an execfile in main), and create Cling equivalents for any newly available python classes.
Definition: TPython.cxx:224
static void * CPPInstance_AsVoidPtr(PyObject *pyobject)
Extract the object pointer held by the CPPInstance pyobject.
Definition: TPython.cxx:533
#define gROOT
Definition: TROOT.h:406
static Bool_t Initialize()
Initialization method: setup the python interpreter and load the ROOT module.
Definition: TPython.cxx:106
PyObject * gCppName
Definition: PyStrings.cxx:10
static void Prompt()
Enter an interactive python session (exit with ^D).
Definition: TPython.cxx:465
static const TPyReturn Eval(const char *expr)
Evaluate a python expression (e.g.
Definition: TPython.cxx:389
PyObject * BindCppObjectNoCast(Cppyy::TCppObject_t object, Cppyy::TCppType_t klass, const unsigned flags=0)
PyObject * gThisModule
Definition: API.cxx:32
static Bool_t CPPOverload_CheckExact(PyObject *pyobject)
Test whether the type of the given pyobject is CPPOverload type.
Definition: TPython.cxx:520
Accessing the Python interpreter from C++.
Definition: TPython.h:29
bool CPPOverload_Check(T *object)
Definition: CPPOverload.h:79
_object PyObject
Definition: PyMethodBase.h:41
bool CPPOverload_CheckExact(T *object)
Definition: CPPOverload.h:85
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition: TClass.h:80
#define PyBytes_Check
Definition: CPyCppyy.h:83
static PyObject * gMainDict
Definition: TPython.cxx:97
PyObject * BindCppObject(Cppyy::TCppObject_t object, Cppyy::TCppType_t klass, const unsigned flags=0)
const Bool_t kFALSE
Definition: RtypesCore.h:90
static Bool_t CPPOverload_Check(PyObject *pyobject)
Test whether the type of the given pyobject is of CPPOverload type or any derived type...
Definition: TPython.cxx:507
bool CPPInstance_CheckExact(T *object)
Definition: CPPInstance.h:128
#define ClassImp(name)
Definition: Rtypes.h:361
static constexpr double L
static Bool_t Import(const char *name)
Import the named python module and create Cling equivalents for its classes and methods.
Definition: TPython.cxx:159
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition: TClass.cxx:2937
Mother of all ROOT objects.
Definition: TObject.h:37
static Bool_t Bind(TObject *object, const char *label)
Bind a ROOT object with, at the python side, the name "label".
Definition: TPython.cxx:439
auto * l
Definition: textangle.C:4
RPY_EXPORTED TCppScope_t GetScope(const std::string &scope_name)
#define CPyCppyy_PyText_CheckExact
Definition: CPyCppyy.h:96
PyObject * gModule
Definition: PyStrings.cxx:24
PyObject * gBases
Definition: PyStrings.cxx:8
const Bool_t kTRUE
Definition: RtypesCore.h:89
PyObject * gName
Definition: PyStrings.cxx:26
char name[80]
Definition: TGX11.cxx:109
#define CPyCppyy_PyText_Check
Definition: CPyCppyy.h:95
static void ExecScript(const char *name, int argc=0, const char **argv=0)
Execute a python stand-alone script, with argv CLI arguments.
Definition: TPython.cxx:294
#define CPyCppyy_PyText_AsString
Definition: CPyCppyy.h:97