00001
00002
00003
00004
00005 #include "PyROOT.h"
00006 #include "PyStrings.h"
00007 #include "PyRootType.h"
00008 #include "ObjectProxy.h"
00009 #include "MethodProxy.h"
00010 #include "TemplateProxy.h"
00011 #include "PropertyProxy.h"
00012 #include "PyBufferFactory.h"
00013 #include "TCustomPyTypes.h"
00014 #include "RootWrapper.h"
00015 #include "Utility.h"
00016 #include "Adapters.h"
00017
00018 #ifdef PYROOT_USE_REFLEX
00019 #include "TRflxCallback.h"
00020 #endif
00021
00022
00023 #include "TROOT.h"
00024 #include "TClass.h"
00025 #include "TObject.h"
00026
00027 #include "TBufferFile.h"
00028
00029
00030 #include <string>
00031
00032
00033
00034 PyObject* gRootModule = 0;
00035
00036
00037
00038 namespace {
00039
00040 using namespace PyROOT;
00041
00042
00043 PyObject* LookupRootEntity( PyObject* pyname, PyObject* args )
00044 {
00045 const char* cname = 0;
00046 if ( pyname && PyROOT_PyUnicode_CheckExact( pyname ) )
00047 cname = PyROOT_PyUnicode_AsString( pyname );
00048 else if ( ! ( args && PyArg_ParseTuple( args, const_cast< char* >( "s" ), &cname ) ) )
00049 return 0;
00050
00051 std::string name = cname;
00052
00053
00054 if ( name.size() <= 2 || name.substr( 0, 2 ) != "__" ) {
00055
00056 PyObject* attr = PyObject_GetAttrString( gRootModule, const_cast< char* >( cname ) );
00057 if ( attr != 0 )
00058 return attr;
00059
00060
00061 PyErr_Clear();
00062 attr = MakeRootClassFromString< TScopeAdapter, TBaseAdapter, TMemberAdapter >( name );
00063 if ( attr != 0 )
00064 return attr;
00065
00066
00067 PyErr_Clear();
00068 attr = GetRootGlobalFromString( name );
00069 if ( attr != 0 )
00070 return attr;
00071
00072
00073 PyErr_Clear();
00074 TObject* object = gROOT->FindObject( name.c_str() );
00075 if ( object != 0 )
00076 return BindRootObject( object, object->IsA() );
00077 }
00078
00079
00080 PyErr_Format( PyExc_AttributeError, "%s", name.c_str() );
00081 return 0;
00082 }
00083
00084
00085 PyDictEntry* RootLookDictString( PyDictObject* mp, PyObject* key, Long_t hash )
00086 {
00087
00088 PyDictEntry* ep = (*gDictLookupOrg)( mp, key, hash );
00089 if ( ! ep || ep->me_value != 0 || gDictLookupActive )
00090 return ep;
00091
00092
00093 if ( PyDict_GetItem( PyEval_GetBuiltins(), key ) != 0 ) {
00094 return ep;
00095 }
00096
00097
00098 gDictLookupActive = kTRUE;
00099
00100
00101 PyObject* val = LookupRootEntity( key, 0 );
00102
00103 if ( val != 0 ) {
00104
00105 if ( PropertyProxy_Check( val ) ) {
00106
00107 Py_INCREF( key );
00108 ep->me_key = key;
00109 ep->me_hash = hash;
00110 ep->me_value = Py_TYPE(val)->tp_descr_get( val, NULL, NULL );
00111 } else {
00112
00113 ((DictLookup_t&)mp->ma_lookup) = gDictLookupOrg;
00114 if ( PyDict_SetItem( (PyObject*)mp, key, val ) == 0 ) {
00115 ep = (*gDictLookupOrg)( mp, key, hash );
00116 } else {
00117 ep->me_key = 0;
00118 ep->me_value = 0;
00119 }
00120 ((DictLookup_t&)mp->ma_lookup) = RootLookDictString;
00121 }
00122
00123
00124 Py_DECREF( val );
00125 } else
00126 PyErr_Clear();
00127
00128
00129 gDictLookupActive = kFALSE;
00130
00131 return ep;
00132 }
00133
00134
00135 PyObject* SetRootLazyLookup( PyObject*, PyObject* args )
00136 {
00137 PyDictObject* dict = 0;
00138 if ( ! PyArg_ParseTuple( args, const_cast< char* >( "O!" ), &PyDict_Type, &dict ) )
00139 return 0;
00140
00141 ((DictLookup_t&)dict->ma_lookup) = RootLookDictString;
00142
00143 Py_INCREF( Py_None );
00144 return Py_None;
00145 }
00146
00147
00148 PyObject* MakeRootTemplateClass( PyObject*, PyObject* args )
00149 {
00150
00151 Py_ssize_t nArgs = PyTuple_GET_SIZE( args );
00152 if ( nArgs < 2 ) {
00153 PyErr_Format( PyExc_TypeError, "too few arguments for template instantiation" );
00154 return 0;
00155 }
00156
00157
00158 PyObject* pyname = PyROOT_PyUnicode_FromString(
00159 PyROOT_PyUnicode_AsString( PyTuple_GET_ITEM( args, 0 ) ) );
00160
00161
00162 if ( ! Utility::BuildTemplateName( pyname, args, 1 ) ) {
00163 Py_DECREF( pyname );
00164 return 0;
00165 }
00166
00167 std::string name = PyROOT_PyUnicode_AsString( pyname );
00168 Py_DECREF( pyname );
00169
00170 return MakeRootClassFromString< TScopeAdapter, TBaseAdapter, TMemberAdapter >( name );
00171 }
00172
00173
00174 void* GetObjectProxyAddress( PyObject*, PyObject* args )
00175 {
00176
00177 ObjectProxy* pyobj = 0;
00178 PyObject* pyname = 0;
00179 if ( PyArg_ParseTuple( args, const_cast< char* >( "O|O!" ), &pyobj,
00180 &PyROOT_PyUnicode_Type, &pyname ) &&
00181 ObjectProxy_Check( pyobj ) && pyobj->fObject ) {
00182
00183 if ( pyname != 0 ) {
00184
00185 PropertyProxy* pyprop = 0;
00186
00187 PyObject* pyclass = PyObject_GetAttr( (PyObject*)pyobj, PyStrings::gClass );
00188
00189 if ( pyclass ) {
00190 PyObject* dict = PyObject_GetAttr( pyclass, PyStrings::gDict );
00191 pyprop = (PropertyProxy*)PyObject_GetItem( dict, pyname );
00192 Py_DECREF( dict );
00193 }
00194 Py_XDECREF( pyclass );
00195
00196 if ( PropertyProxy_Check( pyprop ) ) {
00197
00198 void* addr = (void*)pyprop->GetAddress( pyobj );
00199 Py_DECREF( pyprop );
00200 return addr;
00201 }
00202
00203 Py_XDECREF( pyprop );
00204
00205 PyErr_Format( PyExc_TypeError,
00206 "%s is not a valid data member", PyROOT_PyUnicode_AsString( pyname ) );
00207 return 0;
00208 }
00209
00210
00211 return (void*)&pyobj->fObject;
00212 }
00213
00214 PyErr_SetString( PyExc_ValueError, "invalid argument for AddressOf()" );
00215 return 0;
00216 }
00217
00218 PyObject* AddressOf( PyObject* dummy, PyObject* args )
00219 {
00220
00221 void* addr = GetObjectProxyAddress( dummy, args );
00222 if ( addr )
00223 return BufFac_t::Instance()->PyBuffer_FromMemory( (Long_t*)addr, 1 );
00224
00225 return 0;
00226 }
00227
00228 PyObject* AsCObject( PyObject* dummy, PyObject* args )
00229 {
00230
00231 void* addr = GetObjectProxyAddress( dummy, args );
00232 if ( addr )
00233 return PyCObject_FromVoidPtr( (void*)(*(long*)addr), 0 );
00234
00235 return 0;
00236 }
00237
00238
00239 PyObject* BindObject_( void* addr, PyObject* pyname )
00240 {
00241
00242
00243 if ( ! PyROOT_PyUnicode_Check( pyname ) ) {
00244 PyObject* nattr = PyObject_GetAttr( pyname, PyStrings::gName );
00245 if ( nattr )
00246 pyname = nattr;
00247 pyname = PyObject_Str( pyname );
00248 Py_XDECREF( nattr );
00249 } else {
00250 Py_INCREF( pyname );
00251 }
00252
00253 TClass* klass = TClass::GetClass( PyROOT_PyUnicode_AsString( pyname ) );
00254 Py_DECREF( pyname );
00255
00256 if ( ! klass ) {
00257 PyErr_SetString( PyExc_TypeError,
00258 "BindObject expects a valid class or class name as an argument" );
00259 return 0;
00260 }
00261
00262 return BindRootObjectNoCast( addr, klass, kFALSE );
00263 }
00264
00265
00266 PyObject* BindObject( PyObject*, PyObject* args )
00267 {
00268
00269 Py_ssize_t argc = PyTuple_GET_SIZE( args );
00270 if ( argc != 2 ) {
00271 PyErr_Format( PyExc_TypeError,
00272 "BindObject takes exactly 2 argumenst ("PY_SSIZE_T_FORMAT" given)", argc );
00273 return 0;
00274 }
00275
00276
00277 PyObject* pyaddr = PyTuple_GET_ITEM( args, 0 );
00278 void* addr = PyCObject_AsVoidPtr( pyaddr );
00279 if ( PyErr_Occurred() ) {
00280 PyErr_Clear();
00281
00282 addr = PyLong_AsVoidPtr( pyaddr );
00283
00284 if ( PyErr_Occurred() ) {
00285 PyErr_Clear();
00286 PyErr_SetString( PyExc_TypeError,
00287 "BindObject requires a CObject or long integer as first argument" );
00288 return 0;
00289 }
00290 }
00291
00292 return BindObject_( addr, PyTuple_GET_ITEM( args, 1 ) );
00293 }
00294
00295
00296 PyObject* MakeNullPointer( PyObject*, PyObject* args )
00297 {
00298
00299
00300 Py_ssize_t argc = PyTuple_GET_SIZE( args );
00301 if ( argc != 0 && argc != 1 ) {
00302 PyErr_Format( PyExc_TypeError,
00303 "MakeNullPointer takes at most 1 argument ("PY_SSIZE_T_FORMAT" given)", argc );
00304 return 0;
00305 }
00306
00307
00308 if ( argc == 0 ) {
00309 Py_INCREF( Py_None );
00310 return Py_None;
00311 }
00312
00313 return BindObject_( 0, PyTuple_GET_ITEM( args, 0 ) );
00314 }
00315
00316
00317 PyObject* ObjectProxyExpand( PyObject*, PyObject* args )
00318 {
00319
00320 PyObject* pybuf = 0, *pyname = 0;
00321 if ( ! PyArg_ParseTuple( args, const_cast< char* >( "O!O!:__expand__" ),
00322 &PyBytes_Type, &pybuf, &PyBytes_Type, &pyname ) )
00323 return 0;
00324
00325 const char* clname = PyBytes_AS_STRING(pyname);
00326
00327
00328
00329 void* newObj = 0;
00330 if ( strcmp( clname, "TBufferFile" ) == 0 ) {
00331 TBufferFile* buf = new TBufferFile( TBuffer::kWrite );
00332 buf->WriteFastArray( PyBytes_AS_STRING(pybuf), PyBytes_GET_SIZE( pybuf ) );
00333 newObj = buf;
00334 } else {
00335
00336
00337 TBufferFile buf( TBuffer::kRead,
00338 PyBytes_GET_SIZE( pybuf ), PyBytes_AS_STRING( pybuf ), kFALSE );
00339 newObj = buf.ReadObjectAny( 0 );
00340 }
00341
00342 PyObject* result = BindRootObject( newObj, TClass::GetClass( clname ) );
00343 if ( result ) {
00344
00345
00346 ((ObjectProxy*)result)->HoldOn();
00347 }
00348
00349 return result;
00350 }
00351
00352
00353 PyObject* SetMemoryPolicy( PyObject*, PyObject* args )
00354 {
00355 PyObject* policy = 0;
00356 if ( ! PyArg_ParseTuple( args, const_cast< char* >( "O!" ), &PyInt_Type, &policy ) )
00357 return 0;
00358
00359 Long_t l = PyInt_AS_LONG( policy );
00360 if ( Utility::SetMemoryPolicy( (Utility::EMemoryPolicy)l ) ) {
00361 Py_INCREF( Py_None );
00362 return Py_None;
00363 }
00364
00365 PyErr_Format( PyExc_ValueError, "Unknown policy %ld", l );
00366 return 0;
00367 }
00368
00369
00370 PyObject* SetSignalPolicy( PyObject*, PyObject* args )
00371 {
00372 PyObject* policy = 0;
00373 if ( ! PyArg_ParseTuple( args, const_cast< char* >( "O!" ), &PyInt_Type, &policy ) )
00374 return 0;
00375
00376 Long_t l = PyInt_AS_LONG( policy );
00377 if ( Utility::SetSignalPolicy( (Utility::ESignalPolicy)l ) ) {
00378 Py_INCREF( Py_None );
00379 return Py_None;
00380 }
00381
00382 PyErr_Format( PyExc_ValueError, "Unknown policy %ld", l );
00383 return 0;
00384 }
00385
00386
00387 PyObject* SetOwnership( PyObject*, PyObject* args )
00388 {
00389 ObjectProxy* pyobj = 0; PyObject* pykeep = 0;
00390 if ( ! PyArg_ParseTuple( args, const_cast< char* >( "O!O!" ),
00391 &ObjectProxy_Type, (void*)&pyobj, &PyInt_Type, &pykeep ) )
00392 return 0;
00393
00394 (Bool_t)PyLong_AsLong( pykeep ) ? pyobj->HoldOn() : pyobj->Release();
00395
00396 Py_INCREF( Py_None );
00397 return Py_None;
00398 }
00399
00400 }
00401
00402
00403
00404 static PyMethodDef gPyROOTMethods[] = {
00405 { (char*) "MakeRootClass", (PyCFunction)PyROOT::MakeRootClass,
00406 METH_VARARGS, (char*) "PyROOT internal function" },
00407 { (char*) "GetRootGlobal", (PyCFunction)PyROOT::GetRootGlobal,
00408 METH_VARARGS, (char*) "PyROOT internal function" },
00409 { (char*) "LookupRootEntity", (PyCFunction)LookupRootEntity,
00410 METH_VARARGS, (char*) "PyROOT internal function" },
00411 { (char*) "SetRootLazyLookup", (PyCFunction)SetRootLazyLookup,
00412 METH_VARARGS, (char*) "PyROOT internal function" },
00413 { (char*) "MakeRootTemplateClass", (PyCFunction)MakeRootTemplateClass,
00414 METH_VARARGS, (char*) "PyROOT internal function" },
00415 { (char*) "_DestroyPyStrings", (PyCFunction)PyROOT::DestroyPyStrings,
00416 METH_NOARGS, (char*) "PyROOT internal function" },
00417 { (char*) "AddressOf", (PyCFunction)AddressOf,
00418 METH_VARARGS, (char*) "Retrieve address of held object in a buffer" },
00419 { (char*) "AsCObject", (PyCFunction)AsCObject,
00420 METH_VARARGS, (char*) "Retrieve held object in a CObject" },
00421 { (char*) "BindObject", (PyCFunction)BindObject,
00422 METH_VARARGS, (char*) "Create an object of given type, from given address" },
00423 { (char*) "MakeNullPointer", (PyCFunction)MakeNullPointer,
00424 METH_VARARGS, (char*) "Create a NULL pointer of the given type" },
00425 { (char*) "_ObjectProxy__expand__", (PyCFunction)ObjectProxyExpand,
00426 METH_VARARGS, (char*) "Helper method for pickling" },
00427 { (char*) "SetMemoryPolicy", (PyCFunction)SetMemoryPolicy,
00428 METH_VARARGS, (char*) "Determines object ownership model" },
00429 { (char*) "SetSignalPolicy", (PyCFunction)SetSignalPolicy,
00430 METH_VARARGS, (char*) "Trap signals in safe mode to prevent interpreter abort" },
00431 { (char*) "SetOwnership", (PyCFunction)SetOwnership,
00432 METH_VARARGS, (char*) "Modify held C++ object ownership" },
00433 #ifdef PYROOT_USE_REFLEX
00434 { (char*) "EnableReflex", (PyCFunction)PyROOT::TRflxCallback::Enable,
00435 METH_NOARGS, (char*) "Enable PyReflex notification of new types from Reflex" },
00436 { (char*) "DisableReflex", (PyCFunction)PyROOT::TRflxCallback::Disable,
00437 METH_NOARGS, (char*) "Disable PyReflex notification of new types from Reflex" },
00438 #endif
00439 { NULL, NULL, 0, NULL }
00440 };
00441
00442
00443 #if PY_VERSION_HEX >= 0x03000000
00444 struct module_state {
00445 PyObject *error;
00446 };
00447
00448 #define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
00449
00450 static int rootmodule_traverse( PyObject* m, visitproc visit, void* arg )
00451 {
00452 Py_VISIT( GETSTATE( m )->error );
00453 return 0;
00454 }
00455
00456 static int rootmodule_clear( PyObject* m )
00457 {
00458 Py_CLEAR( GETSTATE( m )->error );
00459 return 0;
00460 }
00461
00462
00463 static struct PyModuleDef moduledef = {
00464 PyModuleDef_HEAD_INIT,
00465 "libPyROOT",
00466 NULL,
00467 sizeof(struct module_state),
00468 gPyROOTMethods,
00469 NULL,
00470 rootmodule_traverse,
00471 rootmodule_clear,
00472 NULL
00473 };
00474
00475
00476 #define PYROOT_INIT_ERROR return NULL
00477 extern "C" PyObject* PyInit_libPyROOT()
00478 #else
00479 #define PYROOT_INIT_ERROR return
00480 extern "C" void initlibPyROOT()
00481 #endif
00482 {
00483 using namespace PyROOT;
00484
00485
00486 if ( ! PyROOT::CreatePyStrings() )
00487 PYROOT_INIT_ERROR;
00488
00489
00490 PyObject* dict = PyDict_New();
00491 gDictLookupOrg = (DictLookup_t)((PyDictObject*)dict)->ma_lookup;
00492 Py_DECREF( dict );
00493
00494
00495 #if PY_VERSION_HEX >= 0x03000000
00496 gRootModule = PyModule_Create( &moduledef );
00497 #else
00498 gRootModule = Py_InitModule( const_cast< char* >( "libPyROOT" ), gPyROOTMethods );
00499 #endif
00500 if ( ! gRootModule )
00501 PYROOT_INIT_ERROR;
00502
00503
00504
00505
00506
00507 if ( ! Utility::InitProxy( gRootModule, &PyRootType_Type, "PyRootType" ) )
00508 PYROOT_INIT_ERROR;
00509
00510
00511 if ( ! Utility::InitProxy( gRootModule, &ObjectProxy_Type, "ObjectProxy" ) )
00512 PYROOT_INIT_ERROR;
00513
00514
00515 if ( ! Utility::InitProxy( gRootModule, &MethodProxy_Type, "MethodProxy" ) )
00516 PYROOT_INIT_ERROR;
00517
00518
00519 if ( ! Utility::InitProxy( gRootModule, &TemplateProxy_Type, "TemplateProxy" ) )
00520 PYROOT_INIT_ERROR;
00521
00522
00523 if ( ! Utility::InitProxy( gRootModule, &PropertyProxy_Type, "PropertyProxy" ) )
00524 PYROOT_INIT_ERROR;
00525
00526
00527 if ( ! Utility::InitProxy( gRootModule, &TCustomFloat_Type, "Double" ) )
00528 PYROOT_INIT_ERROR;
00529
00530 if ( ! Utility::InitProxy( gRootModule, &TCustomInt_Type, "Long" ) )
00531 PYROOT_INIT_ERROR;
00532
00533 if ( ! Utility::InitProxy( gRootModule, &TCustomInstanceMethod_Type, "InstanceMethod" ) )
00534 PYROOT_INIT_ERROR;
00535
00536
00537 PyModule_AddObject( gRootModule, (char*)"kMemoryHeuristics", PyInt_FromLong( 1l ) );
00538 PyModule_AddObject( gRootModule, (char*)"kMemoryStrict", PyInt_FromLong( 2l ) );
00539 PyModule_AddObject( gRootModule, (char*)"kSignalFast", PyInt_FromLong( 1l ) );
00540 PyModule_AddObject( gRootModule, (char*)"kSignalSafe", PyInt_FromLong( 2l ) );
00541
00542
00543 PyROOT::InitRoot();
00544
00545
00546 Utility::SetSignalPolicy( gROOT->IsBatch() ? Utility::kFast : Utility::kSafe );
00547
00548
00549 PyModule_AddObject( gRootModule, (char*)"ROOT",
00550 MakeRootClassFromString< TScopeAdapter, TBaseAdapter, TMemberAdapter >( "ROOT" ) );
00551
00552 #if PY_VERSION_HEX >= 0x03000000
00553 Py_INCREF( gRootModule );
00554 return gRootModule;
00555 #endif
00556 }