Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions bindings/pyroot/ROOT.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,11 +132,12 @@ def ismethod( object ):

### configuration ---------------------------------------------------------------
class _Configuration( object ):
__slots__ = [ 'IgnoreCommandLineOptions', 'StartGuiThread', '_gts' ]
__slots__ = [ 'IgnoreCommandLineOptions', 'StartGuiThread', 'ExposeCppMacros', '_gts' ]

def __init__( self ):
self.IgnoreCommandLineOptions = 0
self.StartGuiThread = True
self.ExposeCppMacros = False
self._gts = []

def __setGTS( self, value ):
Expand Down Expand Up @@ -455,7 +456,7 @@ def __getattr2( self, name ): # "running" getattr
return self.module.__all__

# lookup into ROOT (which may cause python-side enum/class/global creation)
attr = _root.LookupRootEntity( name )
attr = _root.LookupRootEntity( name, PyConfig.ExposeCppMacros )

# the call above will raise AttributeError as necessary; so if we get here,
# attr is valid: cache as appropriate, so we don't come back
Expand Down Expand Up @@ -564,6 +565,9 @@ def _finishSchedule( ROOT = self ):
for name in self.module.__pseudo__all__ + _memPolicyAPI + _sigPolicyAPI:
self.__dict__[ name ] = getattr( _root, name )

# the macro NULL is not available from Cling globals, but might be useful
setattr( _root, 'NULL', 0 )

for name in std.stlclasses:
setattr( _root, name, getattr( std, name ) )

Expand Down
127 changes: 64 additions & 63 deletions bindings/pyroot/src/Pythonize.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,11 @@
// Standard
#include <stdexcept>
#include <string>
#include <stdio.h>
#include <utility>

#include <stdio.h>
#include <string.h> // only needed for Cling TMinuit workaround


namespace {

Expand Down Expand Up @@ -1525,6 +1527,31 @@ namespace PyROOT { // workaround for Intel icc on Linux
}
};

//- TMinuit behavior ----------------------------------------------------------
void TMinuitPyCallback( void* vpyfunc, Long_t /* npar */,
Int_t& a0, Double_t* a1, Double_t& a2, Double_t* a3, Int_t a4 ) {
// a void* was passed to keep the interface on builtin types only
PyObject* pyfunc = (PyObject*)vpyfunc;

// prepare arguments
PyObject* pya0 = BufFac_t::Instance()->PyBuffer_FromMemory( &a0, 1 );
PyObject* pya1 = BufFac_t::Instance()->PyBuffer_FromMemory( a1, a0 );
PyObject* pya2 = BufFac_t::Instance()->PyBuffer_FromMemory( &a2, 1 );
PyObject* pya3 = BufFac_t::Instance()->PyBuffer_FromMemory( a3, -1 ); // size unknown

// perform actual call
PyObject* result = PyObject_CallFunction(
pyfunc, (char*)"OOOOi", pya0, pya1, pya2, pya3, a4 );
Py_DECREF( pya3 ); Py_DECREF( pya2 ); Py_DECREF( pya1 ); Py_DECREF( pya0 );

if ( ! result ) {
PyErr_Print();
throw std::runtime_error( "TMinuit python fit function call failed" );
}

Py_XDECREF( result );
}

//- TFN behavior --------------------------------------------------------------
double TFNPyCallback( void* vpyfunc, Long_t npar, double* a0, double* a1 ) {
// a void* was passed to keep the interface on builtin types only
Expand Down Expand Up @@ -1579,49 +1606,6 @@ namespace {
return self;
}

//- TMinuit behavior ----------------------------------------------------------
/* TODO: implement for Cling
int TMinuitPyCallback( G__value* res, G__CONST char*, struct G__param* libp, int hash )
{
// CINT-installable callback function to allow Minuit to call into python.
PyObject* result = 0;

// retrieve function information
PyObject* pyfunc = PyROOT::Utility::GetInstalledMethod( G__value_get_tagnum(res) );
if ( ! pyfunc )
return 0;

// prepare arguments
PyObject* arg1 = BufFac_t::Instance()->PyBuffer_FromMemory(
G__Intref(&libp->para[0]), 1 );
int npar = *G__Intref(&libp->para[0]);

PyObject* arg2 = BufFac_t::Instance()->PyBuffer_FromMemory(
(Double_t*)G__int(libp->para[1]), npar );

PyObject* arg3 = BufFac_t::Instance()->PyBuffer_FromMemory(
G__Doubleref(&libp->para[2]), 1 );

PyObject* arg4 = BufFac_t::Instance()->PyBuffer_FromMemory(
(Double_t*)G__int(libp->para[3]), -1 ); // size unknown

// perform actual call
result = PyObject_CallFunction( pyfunc, (char*)"OOOOi",
arg1, arg2, arg3, arg4, (int)G__int(libp->para[4]) );
Py_DECREF( arg4 ); Py_DECREF( arg3 ); Py_DECREF( arg2 ); Py_DECREF( arg1 );

if ( ! result ) {
PyErr_Print();
throw std::runtime_error( "TMinuit python fit function call failed" );
}

Py_XDECREF( result );

G__setnull( res );
return ( 1 || hash || res || libp );
}

*/

//____________________________________________________________________________
class TPretendInterpreted: public PyCallable {
Expand Down Expand Up @@ -1768,7 +1752,6 @@ namespace {


//- TMinuit behavior -----------------------------------------------------------
/* TODO: implement for Cling
class TMinuitSetFCN : public TPretendInterpreted {
public:
TMinuitSetFCN( int nArgs = 1 ) : TPretendInterpreted( nArgs ) {}
Expand Down Expand Up @@ -1798,28 +1781,50 @@ namespace {
if ( ! IsCallable( pyfunc ) )
return 0;

// use callable name (if available) as identifier
PyObject* pyname = PyObject_GetAttr( pyfunc, PyStrings::gName );
const char* name = "dummy";
if ( pyname != 0 )
name = PyROOT_PyUnicode_AsString( pyname );
// create signature
std::vector<std::string> signature; signature.reserve( 5 );
signature.push_back( "Int_t&" );
signature.push_back( "Double_t*" );
signature.push_back( "Double_t&" );
signature.push_back( "Double_t*" );
signature.push_back( "Int_t" );

// registration with CINT
Long_t fid = Utility::InstallMethod( 0, pyfunc, name, 0,
"i - - 1 - - D - - 0 - - d - - 1 - - D - - 0 - - i - - 0 - -",
(void*)TMinuitPyCallback, 5 );
Py_XDECREF( pyname );
// registration with Cling
void* fptr = Utility::CreateWrapperMethod(
pyfunc, 5, "void", signature, "TMinuitPyCallback" );
if ( ! fptr /* PyErr was set */ )
return 0;

// get function
// get setter function
MethodProxy* method =
(MethodProxy*)PyObject_GetAttr( (PyObject*)self, PyStrings::gSetFCN );

// CLING WORKAROUND: SetFCN(void* fun) is deprecated but for whatever reason
// still available yet not functional; select the correct one based on its
// signature of the full function pointer
PyCallable* setFCN = 0;
const MethodProxy::Methods_t& methods = method->fMethodInfo->fMethods;
for ( MethodProxy::Methods_t::const_iterator im = methods.begin(); im != methods.end(); ++im ) {
PyObject* sig = (*im)->GetSignature();
if ( strstr( PyROOT_PyUnicode_AsString( sig ), "Double_t&" ) ) {
// the comparison was not exact, but this is just a workaround
setFCN = *im;
Py_DECREF( sig );
break;
}
Py_DECREF( sig );
}
// END CLING WORKAROUND

// build new argument array
PyObject* newArgs = PyTuple_New( 1 );
PyTuple_SET_ITEM( newArgs, 0, PyROOT_PyCapsule_New( (void*)fid, NULL, NULL ) );
PyTuple_SET_ITEM( newArgs, 0, PyROOT_PyCapsule_New( fptr, NULL, NULL ) );

// re-run
PyObject* result = PyObject_CallObject( (PyObject*)method, newArgs );
// CLING WORKAROUND: this is to be the call once TMinuit is fixed:
// PyObject* result = PyObject_CallObject( (PyObject*)method, newArgs );
PyObject* result = setFCN->operator()( self, newArgs, NULL );
// END CLING WORKAROUND

// done, may have worked, if not: 0 is returned
Py_DECREF( newArgs );
Expand Down Expand Up @@ -1856,14 +1861,13 @@ namespace {
return TMinuitSetFCN::operator()( self, args, 0, 0, release_gil );
}
};
*/

//- Fit::TFitter behavior ------------------------------------------------------
PyObject* gFitterPyCallback = 0;

void FitterPyCallback( int& npar, double* gin, double& f, double* u, int flag )
{
// CINT-callable callback for Fit::Fitter derived objects.
// Cling-callable callback for Fit::Fitter derived objects.
PyObject* result = 0;

// prepare arguments
Expand Down Expand Up @@ -1891,7 +1895,6 @@ namespace {
Py_XDECREF( result );
}


class TFitterFitFCN : public TPretendInterpreted {
public:
TFitterFitFCN() : TPretendInterpreted( 2 ) {}
Expand Down Expand Up @@ -2300,13 +2303,11 @@ Bool_t PyROOT::Pythonize( PyObject* pyclass, const std::string& name )
if ( name == "TFunction" ) // allow direct call
return Utility::AddToClass( pyclass, "__call__", (PyCFunction) TFunctionCall );

/* TODO: implement for Cling
if ( name == "TMinuit" ) // allow call with python callable
return Utility::AddToClass( pyclass, "SetFCN", new TMinuitSetFCN );

if ( name == "TFitter" ) // allow call with python callable (this is not correct)
return Utility::AddToClass( pyclass, "SetFCN", new TMinuitFitterSetFCN );
*/

if ( name == "Fitter" ) // really Fit::Fitter, allow call with python callable
return Utility::AddToClass( pyclass, "FitFCN", new TFitterFitFCN );
Expand Down
19 changes: 17 additions & 2 deletions bindings/pyroot/src/RootModule.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

// Standard
#include <string>
#include <sstream>


//- from Python's dictobject.c -------------------------------------------------
Expand Down Expand Up @@ -73,10 +74,10 @@ namespace {
PyObject* LookupRootEntity( PyObject* pyname, PyObject* args )
{
// Find a match within the ROOT module for something with name 'pyname'.
const char* cname = 0;
const char* cname = 0; long macro_ok = 0;
if ( pyname && PyROOT_PyUnicode_CheckExact( pyname ) )
cname = PyROOT_PyUnicode_AsString( pyname );
else if ( ! ( args && PyArg_ParseTuple( args, const_cast< char* >( "s" ), &cname ) ) )
else if ( ! ( args && PyArg_ParseTuple( args, const_cast< char* >( "s|l" ), &cname, &macro_ok ) ) )
return 0;

// we may have been destroyed if this code is called during shutdown
Expand Down Expand Up @@ -111,6 +112,20 @@ namespace {
TObject* object = gROOT->FindObject( name.c_str() );
if ( object != 0 )
return BindRootObject( object, object->IsA() );

// 5th attempt: check macro's (debatable, but this worked in CINT)
if ( macro_ok ) {
PyErr_Clear();
std::ostringstream ismacro;
ismacro << "#ifdef " << name << "\n_pyroot_" << name << "=" << name
<< ";true;\n#else\nfalse;\n#endif";
if ( gROOT->ProcessLine( ismacro.str().c_str() ) ) {
// can now retrieve this as a global
attr = GetRootGlobalFromString( "_pyroot_"+name );
if ( attr != 0 )
return attr;
}
}
}

// still here? raise attribute error
Expand Down
8 changes: 0 additions & 8 deletions bindings/pyroot/src/TPyClassGenerator.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,6 @@ TClass* TPyClassGenerator::GetClass( const char* name, Bool_t load, Bool_t silen
std::ostringstream proxyCode;
proxyCode << "class " << clName << " {\nprivate:\n PyObject* fPyObject;\npublic:\n";

/*
// special case: constructor; add method and store callback
PyROOT::Utility::InstallMethod( &gcl, pyclass, clName, 0, "ellipsis", (void*)PyCtorCallback );
*/
// loop over and add member functions
Bool_t hasConstructor = kFALSE;
for ( int i = 0; i < PyList_GET_SIZE( attrs ); ++i ) {
Expand Down Expand Up @@ -139,10 +135,6 @@ TClass* TPyClassGenerator::GetClass( const char* name, Bool_t load, Bool_t silen
else
proxyCode << " TPyArg::CallConstructor(fPyObject, (PyObject*)" << (void*)pyclass << ", v)";
proxyCode << ";\n }\n";
/* if ( mtName != "__init__" ) {
PyROOT::Utility::InstallMethod(
&gcl, attr, mtName, "TPyReturn", "ellipsis", (void*)PyMemFuncCallback );
} */
}

// no decref of attr for now (b/c of hard-wired ptr); need cleanup somehow
Expand Down
17 changes: 17 additions & 0 deletions core/meta/src/TCling.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,23 @@ extern "C" int TCling__AutoLoadCallback(const char* className)
return gCling->AutoLoad(cls.c_str());
}

extern "C" int TCling__CompileMacro(const char *fileName, const char *options)
{
string file(fileName);
string opt(options);
return gSystem->CompileMacro(file.c_str(), opt.c_str());
}

extern "C" string TCling__SplitAclicMode(const char* fileName, string &mode,
string &args, string &io)
{
string file(fileName);
TString fname, amode, arguments, aclicio;
fname = gSystem->SplitAclicMode(file.c_str(), amode, arguments, aclicio);
mode = amode.Data(); args = arguments.Data(); io = aclicio.Data();
return string(fname.Data());
}

//______________________________________________________________________________
//
//
Expand Down
Loading