coriolis/hurricane/src/viewer/Script.cpp

310 lines
7.9 KiB
C++

// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2008-2015, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | V L S I B a c k e n d D a t a - B a s e |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./hurricane/viewer/Script.cpp" |
// +-----------------------------------------------------------------+
#if !defined(__PYTHON_MODULE__)
#include <Python.h>
#include <sstream>
#include "hurricane/Error.h"
#include "hurricane/Cell.h"
#include "hurricane/isobar/PyCell.h"
#include "hurricane/viewer/PyCellViewer.h"
#include "hurricane/viewer/Script.h"
namespace Isobar {
using std::string;
using Hurricane::Cell;
using Hurricane::CellViewer;
// -------------------------------------------------------------------
// Class : "Isobar::Script".
vector<string> Script::_pathes;
void Script::addPath ( const string& path )
{ _pathes.push_back ( path ); }
void Script::removePath ( const string& path )
{
vector<string>::iterator ipath = _pathes.begin();
for ( ; ipath != _pathes.end() ; ++ipath ) {
if ( (*ipath) == path ) {
_pathes.erase ( ipath );
return;
}
}
}
Script::Script ( const string& name )
: _initModuleNames()
, _initModules ()
, _moduleName (name)
, _sysModule (NULL)
, _hurricaneModule(NULL)
, _userModule (NULL)
, _pyFunction (NULL)
, _pyArgs (NULL)
, _pyKw (NULL)
, _pyResult (NULL)
, _globalState (NULL)
, _subInterpreter (NULL)
, _flags (0)
{ }
Script::~Script ()
{ finalize(); }
Script* Script::create ( const std::string& name )
{
Script* script = new Script ( name );
return script;
}
void Script::destroy ()
{
delete this;
}
void Script::setUserModuleName ( const std::string& name )
{
finalize();
_moduleName = name;
}
bool Script::addInitModuleName ( std::string name )
{
for ( auto moduleName : _initModuleNames ) {
if (name == moduleName) return false;
}
_initModuleNames.push_back( name );
return true;
}
PyObject* Script::getFunction ( std::string function )
{
if (not _userModule) return NULL;
PyObject* pyFunction = PyObject_GetAttrString( _userModule, const_cast<char*>(function.c_str()) );
if ( (pyFunction == NULL) or not PyCallable_Check(pyFunction) )
return NULL;
return pyFunction;
}
bool Script::runFunction ( const std::string& function, Cell* cell, unsigned int flags )
{
bool returnCode = true;
initialize();
_pyFunction = PyObject_GetAttrString( _userModule, const_cast<char*>(function.c_str()) );
if ( (_pyFunction == NULL) or not PyCallable_Check(_pyFunction) ) {
finalize();
throw Error( "Python module %s doesn't contains any %s function."
, _moduleName.c_str(),function.c_str());
}
_pyArgs = PyTuple_New( 0 );
_pyResult = PyObject_Call( _pyFunction, _pyArgs, _pyKw );
_pyArgs = NULL;
_pyKw = NULL;
if (_pyResult == NULL) {
cerr << "Something has gone slightly wrong" << endl;
}
if (PyErr_Occurred()) {
PyErr_Print();
returnCode = false;
}
finalize();
return returnCode;
}
PyObject* Script::callFunction ( const std::string& function, PyObject* pyArgs )
{
if (_userModule == NULL) {
if (PyErr_Occurred()) PyErr_Print();
return NULL;
}
_pyFunction = PyObject_GetAttrString( _userModule, const_cast<char*>(function.c_str()) );
if ( (_pyFunction == NULL) or not PyCallable_Check(_pyFunction) ) {
cerr << Error( "Python module %s doesn't contains any %s function."
, _moduleName.c_str(),function.c_str()) << endl;
return NULL;
}
_pyResult = PyObject_Call( _pyFunction, pyArgs, NULL );
if (_pyResult == NULL) {
cerr << "Something has gone slightly wrong" << endl;
return NULL;
}
if (PyErr_Occurred()) PyErr_Print();
return _pyResult;
}
PyObject* Script::_importSys ( unsigned int flags )
{
_sysModule = _importModule( "sys", flags );
PyObject* path = PyObject_GetAttrString( _sysModule, "path" );
if (path == NULL) {
if (flags & NoThrow) return NULL;
throw Error("Script::_importSys(): No \"sys.path\" attribute.");
}
vector<string>::iterator ipath = _pathes.begin();
for ( ; ipath != _pathes.end() ; ++ipath ) {
PyObject* element = PyString_FromString( const_cast<char*>((*ipath).c_str()) );
PyList_Insert( path, 0, element );
}
return _sysModule;
}
PyObject* Script::_importModule ( const string& moduleName, unsigned int flags )
{
if (not Py_IsInitialized()) {
if (flags & NoThrow) return NULL;
throw Error( "Script::_importModule(): Called before Py_Initialize() while importing <%s>."
, moduleName.c_str() );
}
PyObject* module = PyImport_ImportModule( const_cast<char*>(moduleName.c_str()) );
if (module == NULL) {
if (PyErr_Occurred()) {
PyErr_Print();
}
if (flags & NoThrow) return NULL;
throw Error( "Script::_importModule(): Unable to load module <%s>.",moduleName.c_str() );
}
return module;
}
bool Script::initialize ( unsigned int flags )
{
if (Py_IsInitialized()) {
// Python is already running. Launch a sub-interpreter.
_globalState = PyThreadState_Get();
_subInterpreter = Py_NewInterpreter();
} else
Py_Initialize();
if (not Py_IsInitialized()) {
if (flags & NoThrow) return false;
throw Error( "Script::initialize(): Unable to initialize the Python interpreter (<%s>)."
, _moduleName.c_str());
}
_flags |= Initialized;
_importSys ( flags );
for ( auto moduleName : _initModuleNames )
_initModules.push_back( _importModule(moduleName,flags) );
_importHurricane( flags );
_importUser ( flags );
return true;
}
void Script::finalize ()
{
if (not Py_IsInitialized()) return;
if (not (_flags & Initialized)) return;
_flags &= ~Initialized;
if (_subInterpreter != NULL) {
Py_EndInterpreter(_subInterpreter);
PyThreadState_Swap(_globalState);
_subInterpreter = NULL;
} else {
if ( _userModule != NULL ) { Py_DECREF ( _userModule ); }
if ( _hurricaneModule != NULL ) { Py_DECREF ( _hurricaneModule ); }
if ( _sysModule != NULL ) { Py_DECREF ( _sysModule ); }
if ( _pyResult != NULL ) { Py_DECREF ( _pyResult ); }
if ( _pyArgs != NULL ) { Py_DECREF ( _pyArgs ); }
if ( _pyFunction != NULL ) { Py_DECREF ( _pyFunction ); }
for ( size_t i=0 ; i<_initModules.size() ; ++i ) {
if (_initModules[i]) {
Py_DECREF( _initModules[i] );
_initModules[i] = NULL;
}
}
_initModules.clear();
Py_Finalize ();
_userModule = NULL;
_sysModule = NULL;
_hurricaneModule = NULL;
_pyFunction = NULL;
_pyArgs = NULL;
_pyResult = NULL;
}
}
void Script::addKwArgument ( const char* key, PyObject* object )
{
if (_pyKw == NULL) _pyKw = PyDict_New();
PyObject* pyKey = PyString_FromString( key );
if (PyDict_Contains(_pyKw,pyKey) == 1) {
cerr << Error( "Script::addKwArgument(): Attempt to add twice key %s (nothing done)."
, key ) << endl;
return;
}
PyDict_SetItem( _pyKw, pyKey, object );
}
} // End of Isobar namespace.
#endif