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 ---------------------------------------------------------------------
97static PyObject *gMainDict = 0;
98
99namespace 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
159Bool_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
224void 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
294void 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
363Bool_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
389const 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
439Bool_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
550PyObject *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}
#define PyBytes_Check
Definition: CPyCppyy.h:83
#define CPyCppyy_PyText_AsString
Definition: CPyCppyy.h:97
#define CPyCppyy_PyText_CheckExact
Definition: CPyCppyy.h:96
#define CPyCppyy_PyText_Check
Definition: CPyCppyy.h:95
_object PyObject
Definition: PyMethodBase.h:41
const Bool_t kFALSE
Definition: RtypesCore.h:90
const Bool_t kTRUE
Definition: RtypesCore.h:89
#define ClassImp(name)
Definition: Rtypes.h:361
char name[80]
Definition: TGX11.cxx:109
static PyObject * gMainDict
Definition: TPython.cxx:97
#define gROOT
Definition: TROOT.h:406
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition: TClass.h:80
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:2948
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
Mother of all ROOT objects.
Definition: TObject.h:37
Accessing the Python interpreter from C++.
Definition: TPython.h:29
static void Prompt()
Enter an interactive python session (exit with ^D).
Definition: TPython.cxx:465
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
static void * CPPInstance_AsVoidPtr(PyObject *pyobject)
Extract the object pointer held by the CPPInstance pyobject.
Definition: TPython.cxx:533
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 Bool_t CPPInstance_CheckExact(PyObject *pyobject)
Test whether the type of the given pyobject is CPPinstance type.
Definition: TPython.cxx:493
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
static void LoadMacro(const char *name)
Execute the give python script as if it were a macro (effectively an execfile in main),...
Definition: TPython.cxx:224
static Bool_t CPPOverload_CheckExact(PyObject *pyobject)
Test whether the type of the given pyobject is CPPOverload type.
Definition: TPython.cxx:520
static Bool_t Initialize()
Initialization method: setup the python interpreter and load the ROOT module.
Definition: TPython.cxx:106
static Bool_t Exec(const char *cmd)
Execute a python statement (e.g. "import ROOT").
Definition: TPython.cxx:363
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
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
static const TPyReturn Eval(const char *expr)
Evaluate a python expression (e.g.
Definition: TPython.cxx:389
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
PyObject * gName
Definition: PyStrings.cxx:26
PyObject * gCppName
Definition: PyStrings.cxx:10
PyObject * gBases
Definition: PyStrings.cxx:8
PyObject * gModule
Definition: PyStrings.cxx:24
PyObject * BindCppObjectNoCast(Cppyy::TCppObject_t object, Cppyy::TCppType_t klass, const unsigned flags=0)
bool CPPOverload_Check(T *object)
Definition: CPPOverload.h:79
bool CPPInstance_Check(T *object)
Definition: CPPInstance.h:118
bool CPPInstance_CheckExact(T *object)
Definition: CPPInstance.h:128
PyObject * gThisModule
Definition: API.cxx:32
PyObject * BindCppObject(Cppyy::TCppObject_t object, Cppyy::TCppType_t klass, const unsigned flags=0)
bool CPPOverload_CheckExact(T *object)
Definition: CPPOverload.h:85
RPY_EXPORTED TCppScope_t GetScope(const std::string &scope_name)
static constexpr double L
auto * l
Definition: textangle.C:4