// @(#)root/pyroot:$Name: $:$Id: TPython.cxx,v 1.12 2005/09/09 05:19:10 brun Exp $
// Author: Wim Lavrijsen, Apr 2004
// Bindings
#include "PyROOT.h"
#include "TPython.h"
#include "ObjectProxy.h"
#include "RootWrapper.h"
// ROOT
#include "TROOT.h"
#include "TObject.h"
// Standard
#include <stdio.h>
#include <Riostream.h>
#include <string>
//______________________________________________________________________________
// Python interpreter access
// =========================
//
// The TPython class allows for access to python objects from CINT. The current
// functionality is only basic: ROOT objects and builtin types can freely cross
// the boundary between the two interpreters, python objects can be instantiated
// and their methods can be called. All other cross-coding is based on strings
// that are run on the python interpreter.
//
// Examples:
//
// $ cat MyPyClass.py
// print 'creating class MyPyClass ... '
//
// class MyPyClass:
// def __init__( self ):
// print 'in MyPyClass.__init__'
//
// def gime( self, what ):
// return what
//
// $ root -l
// // Execute a string of python code.
// root [0] TPython::Exec( "print \'Hello World!\'" );
// Hello World!
//
// // Create a TBrowser on the python side, and transfer it back and forth.
// // Note the required explicit (void*) cast!
// root [1] TBrowser* b = (void*)TPython::Eval( "ROOT.TBrowser()" );
// root [2] TPython::Bind( b, "b" );
// root [3] b == (void*) TPython::Eval( "b" )
// (int)1
//
// // Builtin variables can cross-over by using implicit casts.
// root [4] int i = TPython::Eval( "1 + 1" );
// root [5] i
// (int)2
//
// // Load a python module with a class definition, and use it.
// root [6] TPython::LoadMacro( "MyPyClass.py" );
// creating class MyPyClass ...
// root [7] MyPyClass m;
// in MyPyClass.__init__
// root [8] char* s = m.gime( "aap" );
// root [9] s
// (char* 0x41ee7754)"aap"
//
// It is possible to switch between interpreters by calling "TPython::Prompt()"
// on the CINT side, while returning with ^D (EOF). State is preserved between
// successive switches.
//- data ---------------------------------------------------------------------
ClassImp(TPython)
namespace {
PyObject* gMainDict = 0;
PyObject* gClassString = 0;
PyObject* gNameString = 0;
PyObject* gModuleString = 0;
} // unnamed namespace
//- static public members ----------------------------------------------------
Bool_t TPython::Initialize()
{
// Private initialization method: setup the python interpreter and load the
// ROOT module.
if ( ! Py_IsInitialized() ) {
// this happens if CINT comes in first
PyEval_InitThreads();
Py_Initialize();
// try again
if ( ! Py_IsInitialized() ) {
// give up ...
std::cerr << "Error: python has not been intialized; returning." << std::endl;
return kFALSE;
}
// set argv
char* argv[] = { const_cast< char* >( "root" ) };
PySys_SetArgv( sizeof(argv)/sizeof(argv[0]), argv );
// force loading of ROOT
PyRun_SimpleString( const_cast< char* >( "import ROOT" ) );
}
if ( ! gMainDict ) {
// initialize some handy strings
gClassString = PyString_FromString( "__class__" );
gNameString = PyString_FromString( "__name__" );
gModuleString = PyString_FromString( "__module__" );
// retrieve the main dictionary
gMainDict = PyModule_GetDict(
PyImport_AddModule( const_cast< char* >( "__main__" ) ) );
Py_INCREF( gMainDict );
}
// declare success ...
return kTRUE;
}
//____________________________________________________________________________
void TPython::LoadMacro( const char* name )
{
// Execute the give python script as if it were a macro (effectively an
// execfile in __main__), and create CINT equivalents for any newly available
// python classes.
// setup
if ( ! Initialize() )
return;
// obtain a reference to look for new classes later
PyObject* old = PyDict_Values( gMainDict );
// actual execution
Exec( (std::string( "execfile(\"" ) + name + "\")").c_str() );
// obtain new __main__ contents
PyObject* current = PyDict_Values( gMainDict );
// create CINT classes for all new python classes
for ( int i = 0; i < PyList_GET_SIZE( current ); ++i ) {
PyObject* value = PyList_GET_ITEM( current, i );
Py_INCREF( value );
if ( ! PySequence_Contains( old, value ) ) {
// collect classes
if ( PyClass_Check( value ) ||
PyObject_HasAttrString( value, const_cast< char* >( "__bases__" ) ) ) {
// force class creation
PyObject* str = PyObject_Str( value );
gROOT->GetClass( PyString_AS_STRING( str ) );
Py_DECREF( str );
}
}
Py_DECREF( value );
}
Py_DECREF( current );
Py_DECREF( old );
};
//____________________________________________________________________________
void TPython::Exec( const char* cmd )
{
// Execute a python statement (e.g. "import ROOT").
// setup
if ( ! Initialize() )
return;
// execute the command
PyObject* result =
PyRun_String( const_cast< char* >( cmd ), Py_file_input, gMainDict, gMainDict );
// test for error
if ( result )
Py_DECREF( result );
else
PyErr_Print();
}
//____________________________________________________________________________
const TPyReturn TPython::Eval( const char* expr )
{
// Evaluate a python expression (e.g. "ROOT.TBrowser()").
//
// Caution: do not hold on to the return value: either store it in a builtin
// type (implicit casting will work), or in a pointer to a ROOT object (explicit
// casting to a void* is required).
// setup
if ( ! Initialize() )
return TPyReturn();
// evaluate the expression
PyObject* result =
PyRun_String( const_cast< char* >( expr ), Py_eval_input, gMainDict, gMainDict );
// report errors as appropriate; return void
if ( ! result ) {
PyErr_Print();
return TPyReturn();
}
// results that require no converion
if ( result == Py_None || PyROOT::ObjectProxy_Check( result ) )
return TPyReturn( result );
// explicit conversion for python type required
PyObject* pyclass = PyObject_GetAttr( result, gClassString );
if ( pyclass != 0 ) {
// retrieve class name and the module in which it resides
PyObject* name = PyObject_GetAttr( pyclass, gNameString );
PyObject* module = PyObject_GetAttr( pyclass, gModuleString );
// concat name
std::string qname =
std::string( PyString_AS_STRING( module ) ) + '.' + PyString_AS_STRING( name );
Py_DECREF( module );
Py_DECREF( name );
Py_DECREF( pyclass );
// locate ROOT style class with this name
TClass* klass = gROOT->GetClass( qname.c_str() );
// construct general ROOT python object that pretents to be of class 'klass'
if ( klass != 0 )
return TPyReturn( result );
} else
PyErr_Clear();
// no conversion, return null pointer object
Py_DECREF( result );
return TPyReturn();
}
//____________________________________________________________________________
Bool_t TPython::Bind( TObject* object, const char* label )
{
// Bind a ROOT object with, at the python side, the name "label".
// check given address and setup
if ( ! ( object && Initialize() ) )
return kFALSE;
// bind object in the main namespace
TClass* klass = object->IsA();
if ( klass != 0 ) {
PyObject* bound = PyROOT::BindRootObject( (void*)object, klass );
if ( bound ) {
Bool_t bOk = PyDict_SetItemString( gMainDict, const_cast< char* >( label ), bound ) == 0;
Py_DECREF( bound );
return bOk;
}
}
return kFALSE;
}
//____________________________________________________________________________
void TPython::Prompt() {
// Enter an interactive python session (exit with ^D). State is preserved
// between successive calls.
// setup
if ( ! Initialize() ) {
return;
}
// enter i/o interactive mode
PyRun_InteractiveLoop( stdin, const_cast< char* >( "\0" ) );
}
ROOT page - Class index - Class Hierarchy - Top of the page
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.