Logo ROOT  
Reference Guide
RootModule.cxx
Go to the documentation of this file.
1// @(#)root/pyroot:$Id$
2// Author: Wim Lavrijsen, Apr 2004
3
4// Bindings
5#include "PyROOT.h"
6#include "PyStrings.h"
7#include "PyRootType.h"
8#include "ObjectProxy.h"
9#include "MethodProxy.h"
10#include "TemplateProxy.h"
11#include "PropertyProxy.h"
12#include "TPyBufferFactory.h"
13#include "TCustomPyTypes.h"
14#include "TTupleOfInstances.h"
15#include "RootWrapper.h"
16#include "TCallContext.h"
17#include "Utility.h"
18
19// ROOT
20#include "TObject.h" // for FindObject
21#include "TROOT.h" // for ProcessLine and FindObject
22
23
24#include "TBufferFile.h" // for pickling
25
26// Standard
27#include <string>
28#include <sstream>
29#include <utility>
30#include <vector>
31
32
33//- from Python's dictobject.c -------------------------------------------------
34#if PY_VERSION_HEX >= 0x03030000
35 typedef struct PyDictKeyEntry {
36 /* Cached hash code of me_key. */
37 Py_hash_t me_hash;
38 PyObject *me_key;
39 PyObject *me_value; /* This field is only meaningful for combined tables */
40 } PyDictEntry;
41
42 typedef struct _dictkeysobject {
43 Py_ssize_t dk_refcnt;
44 Py_ssize_t dk_size;
45 dict_lookup_func dk_lookup;
46 Py_ssize_t dk_usable;
47 PyDictKeyEntry dk_entries[1];
48 } PyDictKeysObject;
49
50#define PYROOT_GET_DICT_LOOKUP( mp )\
51 ((dict_lookup_func&)mp->ma_keys->dk_lookup)
52
53#else
54
55#define PYROOT_GET_DICT_LOOKUP( mp )\
56 ((dict_lookup_func&)mp->ma_lookup)
57
58#endif
59
60//- data -----------------------------------------------------------------------
62{
63 return PyBytes_FromString( "nullptr" );
64}
65
67{
68 Py_FatalError( "deallocating nullptr" );
69}
70
72{
73 return 0;
74}
75
76static PyNumberMethods nullptr_as_number = {
77 0, 0, 0,
78#if PY_VERSION_HEX < 0x03000000
79 0,
80#endif
81 0, 0, 0, 0, 0, 0,
82 (inquiry)nullptr_nonzero, // tp_nonzero (nb_bool in p3)
83 0, 0, 0, 0, 0, 0,
84#if PY_VERSION_HEX < 0x03000000
85 0, // nb_coerce
86#endif
87 0, 0, 0,
88#if PY_VERSION_HEX < 0x03000000
89 0, 0,
90#endif
91 0, 0, 0,
92#if PY_VERSION_HEX < 0x03000000
93 0, // nb_inplace_divide
94#endif
95 0, 0, 0, 0, 0, 0, 0
96#if PY_VERSION_HEX >= 0x02020000
97 , 0 // nb_floor_divide
98#if PY_VERSION_HEX < 0x03000000
99 , 0 // nb_true_divide
100#else
101 , 0 // nb_true_divide
102#endif
103 , 0, 0
104#endif
105#if PY_VERSION_HEX >= 0x02050000
106 , 0 // nb_index
107#endif
108#if PY_VERSION_HEX >= 0x03050000
109 , 0 // nb_matrix_multiply
110 , 0 // nb_inplace_matrix_multiply
111#endif
112
113 };
114
115#if !defined(_MSC_VER)
116#pragma GCC diagnostic push
117#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
118#endif
119
120static PyTypeObject PyNullPtr_t_Type = {
121 PyVarObject_HEAD_INIT( &PyType_Type, 0 )
122 "nullptr_t", // tp_name
123 sizeof(PyObject), // tp_basicsize
124 0, // tp_itemsize
125 nullptr_dealloc, // tp_dealloc (never called)
126 0, 0, 0, 0,
127 nullptr_repr, // tp_repr
128 &nullptr_as_number, // tp_as_number
129 0, 0,
130 (hashfunc)_Py_HashPointer, // tp_hash
131 0, 0, 0, 0, 0, Py_TPFLAGS_DEFAULT, 0, 0, 0, 0, 0, 0, 0,
132 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
133#if PY_VERSION_HEX >= 0x02030000
134 , 0 // tp_del
135#endif
136#if PY_VERSION_HEX >= 0x02060000
137 , 0 // tp_version_tag
138#endif
139#if PY_VERSION_HEX >= 0x03040000
140 , 0 // tp_finalize
141#endif
142#if PY_VERSION_HEX >= 0x03080000
143 , 0 // tp_vectorcall
144#if PY_VERSION_HEX < 0x03090000
145 , 0 // tp_print (python 3.8 only)
146#endif
147#endif
148};
149
150#if !defined(_MSC_VER)
151#pragma GCC diagnostic pop
152#endif
153
155 _PyObject_EXTRA_INIT
157};
158
159namespace PyROOT {
162 std::vector<std::pair<Cppyy::TCppType_t, Cppyy::TCppType_t> > gPinnedTypes;
163 std::vector<Cppyy::TCppType_t> gIgnorePinnings;
164}
165
166
167//- private helpers ------------------------------------------------------------
168namespace {
169
170 using namespace PyROOT;
171
172////////////////////////////////////////////////////////////////////////////////
173
174 PyObject* RootModuleResetCallback( PyObject*, PyObject* )
175 {
176 gRootModule = 0; // reference was borrowed
177 Py_INCREF( Py_None );
178 return Py_None;
179 }
180
181////////////////////////////////////////////////////////////////////////////////
182/// Find a match within the ROOT module for something with name 'pyname'.
183
184 PyObject* LookupCppEntity( PyObject* pyname, PyObject* args )
185 {
186 const char* cname = 0; long macro_ok = 0;
189 else if ( ! ( args && PyArg_ParseTuple( args, const_cast< char* >( "s|l" ), &cname, &macro_ok ) ) )
190 return 0;
191
192 // we may have been destroyed if this code is called during shutdown
193 if ( !gRootModule ) {
194 PyErr_Format( PyExc_AttributeError, "%s", cname );
195 return 0;
196 }
197
198 std::string name = cname;
199
200 // block search for privates
201 if ( name.size() <= 2 || name.substr( 0, 2 ) != "__" ) {
202 // 1st attempt: look in myself
203 PyObject* attr = PyObject_GetAttrString( gRootModule, const_cast< char* >( cname ) );
204 if ( attr != 0 )
205 return attr;
206
207 // 2nd attempt: construct name as a class
208 PyErr_Clear();
209 attr = CreateScopeProxy( name, 0 /* parent */);
210 if ( attr != 0 )
211 return attr;
212
213 // 3rd attempt: lookup name as global variable
214 PyErr_Clear();
215 attr = GetCppGlobal( name );
216 if ( attr != 0 )
217 return attr;
218
219 // 4th attempt: find existing object (e.g. from file)
220 PyErr_Clear();
221 TObject* object = gROOT->FindObject( name.c_str() );
222 if ( object != 0 )
223 return BindCppObject( object, object->IsA()->GetName() );
224
225 // 5th attempt: global enum
226 if (Cppyy::IsEnum(name)) {
227 // enum types (incl. named and class enums)
229 if (enumtype) {
230 // collect the enum values
232 PyObject* dct = PyDict_New();
233 for (Cppyy::TCppIndex_t idata = 0; idata < ndata; ++idata) {
234 PyObject* val = PyLong_FromLongLong(Cppyy::GetEnumDataValue(enumtype, idata));
235 PyDict_SetItemString(dct, Cppyy::GetEnumDataName(enumtype, idata).c_str(), val);
236 Py_DECREF(val);
237 }
238
239 // add the __cppname__ for templates
240 PyObject* cppnamepy = PyROOT_PyUnicode_FromString(cname);
241 PyDict_SetItem(dct, PyStrings::gCppName, cppnamepy);
242 // add also __cpp_name__ for forward compatibility
243 PyDict_SetItem(dct, PyStrings::gCppNameNew, cppnamepy);
244 Py_DECREF(cppnamepy);
245
246 // create new type with labeled values in place
247 PyObject* pybases = PyTuple_New(1);
248 Py_INCREF(&PyInt_Type);
249 PyTuple_SET_ITEM(pybases, 0, (PyObject*)&PyInt_Type);
250 PyObject* argsnt = Py_BuildValue((char*)"sOO", name.c_str(), pybases, dct);
251 attr = Py_TYPE(&PyInt_Type)->tp_new(Py_TYPE(&PyInt_Type), argsnt, nullptr);
252 Py_DECREF(argsnt);
253 Py_DECREF(pybases);
254 Py_DECREF(dct);
255 } else {
256 // presumably not a class enum; simply pretend int
257 Py_INCREF(&PyInt_Type);
258 attr = (PyObject*)&PyInt_Type;
259 }
260 return attr;
261 }
262
263 // 6th attempt: check macro's (debatable, but this worked in CINT)
264 if ( macro_ok ) {
265 PyErr_Clear();
266 std::ostringstream ismacro;
267 ismacro << "#ifdef " << name << "\n_pyroot_" << name << "=" << name
268 << ";true;\n#else\nfalse;\n#endif";
269 if ( gROOT->ProcessLine( ismacro.str().c_str() ) ) {
270 // can now retrieve this as a global
271 attr = GetCppGlobal( "_pyroot_"+name );
272 if ( attr != 0 )
273 return attr;
274 }
275 }
276 }
277
278 // still here? raise attribute error
279 PyErr_Format( PyExc_AttributeError, "%s", name.c_str() );
280 return 0;
281 }
282
283////////////////////////////////////////////////////////////////////////////////
284
285#if PY_VERSION_HEX >= 0x03030000
286 inline PyDictKeyEntry* OrgDictLookup(
287 PyDictObject* mp, PyObject* key, Py_hash_t hash, PyObject*** value_addr )
288 {
289 return (*gDictLookupOrg)( mp, key, hash, value_addr );
290 }
291
292#define PYROOT_ORGDICT_LOOKUP( mp, key, hash, value_addr )\
293 OrgDictLookup( mp, key, hash, value_addr )
294
295 PyDictKeyEntry* RootLookDictString(
296 PyDictObject* mp, PyObject* key, Py_hash_t hash, PyObject*** value_addr )
297#else
298 inline PyDictEntry* OrgDictLookup( PyDictObject* mp, PyObject* key, Long_t hash )
299 {
300 return (*gDictLookupOrg)( mp, key, hash );
301 }
302
303#define PYROOT_ORGDICT_LOOKUP( mp, key, hash, value_addr )\
304 OrgDictLookup( mp, key, hash )
305
306 PyDictEntry* RootLookDictString( PyDictObject* mp, PyObject* key, Long_t hash )
307#endif
308 {
309 // first search dictionary itself
310 PyDictEntry* ep = PYROOT_ORGDICT_LOOKUP( mp, key, hash, value_addr );
311 if ( ! ep || (ep->me_key && ep->me_value) || gDictLookupActive )
312 return ep;
313
314 // filter for builtins
315 if ( PyDict_GetItem( PyEval_GetBuiltins(), key ) != 0 ) {
316 return ep;
317 }
318
319 // all failed, start calling into ROOT
321
322 // ROOT globals (the round-about lookup is to prevent recursion)
323 PyObject* gval = PyDict_GetItem( PyModule_GetDict( gRootModule ), key );
324 if ( gval ) {
325 Py_INCREF( gval );
326 ep->me_value = gval;
327 ep->me_key = key;
328 ep->me_hash = hash;
329#if PY_VERSION_HEX >= 0x03030000
330 *value_addr = &gval;
331#endif
333 return ep;
334 }
335
336 // attempt to get ROOT enum/global/class
337 PyObject* val = LookupCppEntity( key, 0 );
338
339 if ( val != 0 ) {
340 // success ...
341
342 if ( PropertyProxy_CheckExact( val ) ) {
343 // don't want to add to dictionary (the proper place would be the
344 // dictionary of the (meta)class), but modifying ep will be noticed no
345 // matter what; just return the actual value and live with the copy in
346 // the dictionary (mostly, this is correct)
347 PyObject* actual_val = Py_TYPE(val)->tp_descr_get( val, NULL, NULL );
348 Py_DECREF( val );
349 val = actual_val;
350 }
351
352 // add reference to ROOT entity in the given dictionary
353 PYROOT_GET_DICT_LOOKUP( mp ) = gDictLookupOrg; // prevent recursion
354 if ( PyDict_SetItem( (PyObject*)mp, key, val ) == 0 ) {
355 ep = PYROOT_ORGDICT_LOOKUP( mp, key, hash, value_addr );
356 } else {
357 ep->me_key = 0;
358 ep->me_value = 0;
359 }
360 PYROOT_GET_DICT_LOOKUP( mp ) = RootLookDictString; // restore
361
362 // done with val
363 Py_DECREF( val );
364 } else
365 PyErr_Clear();
366
367#if PY_VERSION_HEX >= 0x03030000
368 if ( mp->ma_keys->dk_usable <= 0 ) {
369 // big risk that this lookup will result in a resize, so force it here
370 // to be able to reset the lookup function; of course, this is nowhere
371 // near fool-proof, but should cover interactive usage ...
373 const int maxinsert = 5;
374 PyObject* buf[maxinsert];
375 for ( int varmax = 1; varmax <= maxinsert; ++varmax ) {
376 for ( int ivar = 0; ivar < varmax; ++ivar ) {
377 buf[ivar] = PyROOT_PyUnicode_FromFormat( "__ROOT_FORCE_RESIZE_%d", ivar );
378 PyDict_SetItem( (PyObject*)mp, buf[ivar], Py_None);
379 }
380 for ( int ivar = 0; ivar < varmax; ++ivar ) {
381 PyDict_DelItem( (PyObject*)mp, buf[ivar] );
382 Py_DECREF( buf[ivar] );
383 }
384 if ( 0 < mp->ma_keys->dk_usable )
385 break;
386 }
387
388 // make sure the entry pointer is still valid by re-doing the lookup
389 ep = PYROOT_ORGDICT_LOOKUP( mp, key, hash, value_addr );
390
391 // full reset of all lookup functions
393 PYROOT_GET_DICT_LOOKUP( mp ) = RootLookDictString; // restore
394 }
395#endif
396
397 // stopped calling into ROOT
399
400 return ep;
401 }
402
403////////////////////////////////////////////////////////////////////////////////
404/// Modify the given dictionary to install the lookup function that also
405/// tries the ROOT namespace before failing. Called on a module's dictionary,
406/// this allows for lazy lookups.
407
408 PyObject* SetRootLazyLookup( PyObject*, PyObject* args )
409 {
410 PyDictObject* dict = 0;
411 if ( ! PyArg_ParseTuple( args, const_cast< char* >( "O!" ), &PyDict_Type, &dict ) )
412 return 0;
413
414 // Notwithstanding the code changes, the following does not work for p3.3 and
415 // later: once the dictionary is resized for anything other than an insert (see
416 // hack in RootLookDictString), its lookup function on its keys will revert to
417 // the default (lookdict_unicode_nodummy) and only if the resizing dictionary
418 // has the generic lookdict function as dk_lookup for its keys, will this be
419 // set on the new keys.
420 PYROOT_GET_DICT_LOOKUP( dict ) = RootLookDictString;
421
422 Py_INCREF( Py_None );
423 return Py_None;
424 }
425
426////////////////////////////////////////////////////////////////////////////////
427/// Create a binding for a templated class instantiation.
428
429 PyObject* MakeRootTemplateClass( PyObject*, PyObject* args )
430 {
431 // args is class name + template arguments; build full instantiation
432 Py_ssize_t nArgs = PyTuple_GET_SIZE( args );
433 if ( nArgs < 2 ) {
434 PyErr_Format( PyExc_TypeError, "too few arguments for template instantiation" );
435 return 0;
436 }
437
438 // build "< type, type, ... >" part of class name (modifies pyname)
439 PyObject* pyname = Utility::BuildTemplateName( PyTuple_GET_ITEM( args, 0 ), args, 1 );
440 if ( ! pyname )
441 return 0;
442
443 std::string name = PyROOT_PyUnicode_AsString( pyname );
444 Py_DECREF( pyname );
445
446 return CreateScopeProxy( name );
447 }
448
449////////////////////////////////////////////////////////////////////////////////
450/// Helper to get the address (address-of-address) of various object proxy types.
451
452 void* GetObjectProxyAddress( PyObject*, PyObject* args )
453 {
454 ObjectProxy* pyobj = 0;
455 PyObject* pyname = 0;
456 if ( PyArg_ParseTuple( args, const_cast< char* >( "O|O!" ), &pyobj,
458 ObjectProxy_Check( pyobj ) && pyobj->fObject ) {
459
460 if ( pyname != 0 ) {
461 // locate property proxy for offset info
462 PropertyProxy* pyprop = 0;
463
464 PyObject* pyclass = PyObject_GetAttr( (PyObject*)pyobj, PyStrings::gClass );
465
466 if ( pyclass ) {
467 PyObject* dict = PyObject_GetAttr( pyclass, PyStrings::gDict );
468 pyprop = (PropertyProxy*)PyObject_GetItem( dict, pyname );
469 Py_DECREF( dict );
470 }
471 Py_XDECREF( pyclass );
472
473 if ( PropertyProxy_Check( pyprop ) ) {
474 // this is an address of a value (i.e. &myobj->prop)
475 void* addr = (void*)pyprop->GetAddress( pyobj );
476 Py_DECREF( pyprop );
477 return addr;
478 }
479
480 Py_XDECREF( pyprop );
481
482 PyErr_Format( PyExc_TypeError,
483 "%s is not a valid data member", PyROOT_PyUnicode_AsString( pyname ) );
484 return 0;
485 }
486
487 // this is an address of an address (i.e. &myobj, with myobj of type MyObj*)
488 return (void*)&pyobj->fObject;
489 }
490
491 PyErr_SetString( PyExc_ValueError, "invalid argument for AddressOf()" );
492 return 0;
493 }
494
495 PyObject* _addressof_common( PyObject* dummy ) {
496 if ( dummy == Py_None || dummy == gNullPtrObject ) {
497 Py_INCREF( gNullPtrObject );
498 return gNullPtrObject;
499 }
500 if ( !PyErr_Occurred() ) {
501 PyObject* str = PyObject_Str( dummy );
502 if ( str && PyROOT_PyUnicode_Check( str ) )
503 PyErr_Format( PyExc_ValueError, "unknown object %s", PyBytes_AS_STRING( str ) );
504 else
505 PyErr_Format( PyExc_ValueError, "unknown object at %p", (void*)dummy );
506 Py_XDECREF( str );
507 }
508 return 0;
509 }
510
511 PyObject* AddressOf( PyObject* dummy, PyObject* args )
512 {
513 // Return object proxy address as an indexable buffer.
514 void* addr = GetObjectProxyAddress( dummy, args );
515 if ( addr )
516 return BufFac_t::Instance()->PyBuffer_FromMemory( (Long_t*)addr, sizeof(Long_t) );
517 if ( ! addr && PyTuple_Size( args ) ) {
518 Utility::GetBuffer( PyTuple_GetItem( args, 0 ), '*', 1, addr, kFALSE );
519 if ( addr )
520 return BufFac_t::Instance()->PyBuffer_FromMemory( (Long_t*)&addr, sizeof(Long_t) );
521 }
522 return 0;//_addressof_common( dummy );
523 }
524
525 PyObject* addressof( PyObject* dummy, PyObject* args )
526 {
527 // Return object proxy address as a value (cppyy-style), or the same for an array.
528 void* addr = GetObjectProxyAddress( dummy, args );
529 if ( addr )
530 return PyLong_FromLong( *(Long_t*)addr );
531 else if ( PyTuple_Size( args ) ) {
532 PyErr_Clear();
533 Utility::GetBuffer( PyTuple_GetItem( args, 0 ), '*', 1, addr, kFALSE );
534 if ( addr ) return PyLong_FromLong( (Long_t)addr );
535 }
536 return _addressof_common( dummy );
537 }
538
539 PyObject* AsCObject( PyObject* dummy, PyObject* args )
540 {
541 // Return object proxy as an opaque CObject.
542 void* addr = GetObjectProxyAddress( dummy, args );
543 if ( addr )
544 return PyROOT_PyCapsule_New( (void*)(*(Long_t*)addr), NULL, NULL );
545
546 return 0;
547 }
548
549////////////////////////////////////////////////////////////////////////////////
550/// Helper to factorize the common code between MakeNullPointer and BindObject.
551
552 PyObject* BindObject_( void* addr, PyObject* pyname )
553 {
554 if ( ! PyROOT_PyUnicode_Check( pyname ) ) { // name given as string
555 PyObject* nattr = PyObject_GetAttr( pyname, PyStrings::gCppName );
556 if ( ! nattr ) nattr = PyObject_GetAttr( pyname, PyStrings::gName );
557 if ( nattr ) // object is actually a class
558 pyname = nattr;
559 pyname = PyObject_Str( pyname );
560 Py_XDECREF( nattr );
561 } else {
562 Py_INCREF( pyname );
563 }
564
566 Py_DECREF( pyname );
567
568 if ( ! klass ) {
569 PyErr_SetString( PyExc_TypeError,
570 "BindObject expects a valid class or class name as an argument" );
571 return 0;
572 }
573
574 return BindCppObjectNoCast( addr, klass, kFALSE );
575 }
576
577////////////////////////////////////////////////////////////////////////////////
578/// From a long representing an address or a PyCapsule/CObject, bind to a class.
579
580 PyObject* BindObject( PyObject*, PyObject* args )
581 {
582 Py_ssize_t argc = PyTuple_GET_SIZE( args );
583 if ( argc != 2 ) {
584 PyErr_Format( PyExc_TypeError,
585 "BindObject takes exactly 2 argumenst (" PY_SSIZE_T_FORMAT " given)", argc );
586 return 0;
587 }
588
589 // try to convert first argument: either PyCapsule/CObject or long integer
590 PyObject* pyaddr = PyTuple_GET_ITEM( args, 0 );
591 void* addr = PyROOT_PyCapsule_GetPointer( pyaddr, NULL );
592 if ( PyErr_Occurred() ) {
593 PyErr_Clear();
594
595 addr = PyLong_AsVoidPtr( pyaddr );
596 if ( PyErr_Occurred() ) {
597 PyErr_Clear();
598
599 // last chance, perhaps it's a buffer/array (return from void*)
600 int buflen = Utility::GetBuffer( PyTuple_GetItem( args, 0 ), '*', 1, addr, kFALSE );
601 if ( ! addr || ! buflen ) {
602 PyErr_SetString( PyExc_TypeError,
603 "BindObject requires a CObject or long integer as first argument" );
604 return 0;
605 }
606 }
607 }
608
609 return BindObject_( addr, PyTuple_GET_ITEM( args, 1 ) );
610 }
611
612////////////////////////////////////////////////////////////////////////////////
613/// Create an object of the given type point to NULL (historic note: this
614/// function is older than BindObject(), which can be used instead).
615
616 PyObject* MakeNullPointer( PyObject*, PyObject* args )
617 {
618 Py_ssize_t argc = PyTuple_GET_SIZE( args );
619 if ( argc != 0 && argc != 1 ) {
620 PyErr_Format( PyExc_TypeError,
621 "MakeNullPointer takes at most 1 argument (" PY_SSIZE_T_FORMAT " given)", argc );
622 return 0;
623 }
624
625 // no class given, use None as generic
626 if ( argc == 0 ) {
627 Py_INCREF( Py_None );
628 return Py_None;
629 }
630
631 return BindObject_( 0, PyTuple_GET_ITEM( args, 0 ) );
632 }
633
634////////////////////////////////////////////////////////////////////////////////
635/// This method is a helper for (un)pickling of ObjectProxy instances.
636
637 PyObject* ObjectProxyExpand( PyObject*, PyObject* args )
638 {
639 PyObject* pybuf = 0, *pyname = 0;
640 if ( ! PyArg_ParseTuple( args, const_cast< char* >( "O!O!:__expand__" ),
641 &PyBytes_Type, &pybuf, &PyBytes_Type, &pyname ) )
642 return 0;
643
644 const char* clname = PyBytes_AS_STRING(pyname);
645
646 // make sure that ROOT.py is loaded and fully initialized by accessing on it
647 PyObject* mod = PyImport_ImportModule( (char*)"ROOT" );
648 if ( mod ) {
649 PyObject* dummy = PyObject_GetAttrString( mod, (char*)"kRed" );
650 Py_XDECREF( dummy );
651 Py_DECREF( mod );
652 }
653
654 // TBuffer and its derived classes can't write themselves, but can be created
655 // directly from the buffer, so handle them in a special case
656 void* newObj = 0;
657 if ( strcmp( clname, "TBufferFile" ) == 0 ) {
659 buf->WriteFastArray( PyBytes_AS_STRING(pybuf), PyBytes_GET_SIZE( pybuf ) );
660 newObj = buf;
661 } else {
662 // use the PyString macro's to by-pass error checking; do not adopt the buffer,
663 // as the local TBufferFile can go out of scope (there is no copying)
665 PyBytes_GET_SIZE( pybuf ), PyBytes_AS_STRING( pybuf ), kFALSE );
666 newObj = buf.ReadObjectAny( 0 );
667 }
668
669 PyObject* result = BindCppObject( newObj, clname );
670 if ( result ) {
671 // this object is to be owned by the interpreter, assuming that the call
672 // originated from there
673 ((ObjectProxy*)result)->HoldOn();
674 }
675
676 return result;
677 }
678
679////////////////////////////////////////////////////////////////////////////////
680/// Set the global memory policy, which affects object ownership when objects
681/// are passed as function arguments.
682
683 PyObject* SetMemoryPolicy( PyObject*, PyObject* args )
684 {
685 PyObject* policy = 0;
686 if ( ! PyArg_ParseTuple( args, const_cast< char* >( "O!" ), &PyInt_Type, &policy ) )
687 return 0;
688
689 Long_t l = PyInt_AS_LONG( policy );
690 if ( TCallContext::SetMemoryPolicy( (TCallContext::ECallFlags)l ) ) {
691 Py_INCREF( Py_None );
692 return Py_None;
693 }
694
695 PyErr_Format( PyExc_ValueError, "Unknown policy %ld", l );
696 return 0;
697 }
698
699////////////////////////////////////////////////////////////////////////////////
700/// Set the global signal policy, which determines whether a jmp address
701/// should be saved to return to after a C++ segfault.
702
703 PyObject* SetSignalPolicy( PyObject*, PyObject* args )
704 {
705 PyObject* policy = 0;
706 if ( ! PyArg_ParseTuple( args, const_cast< char* >( "O!" ), &PyInt_Type, &policy ) )
707 return 0;
708
709 Long_t l = PyInt_AS_LONG( policy );
710 if ( TCallContext::SetSignalPolicy( (TCallContext::ECallFlags)l ) ) {
711 Py_INCREF( Py_None );
712 return Py_None;
713 }
714
715 PyErr_Format( PyExc_ValueError, "Unknown policy %ld", l );
716 return 0;
717 }
718
719////////////////////////////////////////////////////////////////////////////////
720/// Set the ownership (True is python-owns) for the given object.
721
722 PyObject* SetOwnership( PyObject*, PyObject* args )
723 {
724 ObjectProxy* pyobj = 0; PyObject* pykeep = 0;
725 if ( ! PyArg_ParseTuple( args, const_cast< char* >( "O!O!" ),
726 &ObjectProxy_Type, (void*)&pyobj, &PyInt_Type, &pykeep ) )
727 return 0;
728
729 (Bool_t)PyLong_AsLong( pykeep ) ? pyobj->HoldOn() : pyobj->Release();
730
731 Py_INCREF( Py_None );
732 return Py_None;
733 }
734
735////////////////////////////////////////////////////////////////////////////////
736/// Add a smart pointer to the list of known smart pointer types.
737
739 {
740 const char* type_name;
741 if ( ! PyArg_ParseTuple( args, const_cast< char* >( "s" ), &type_name ) )
742 return nullptr;
743
744 Cppyy::AddSmartPtrType( type_name );
745
746 Py_RETURN_NONE;
747 }
748
749
750////////////////////////////////////////////////////////////////////////////////
751/// Add a pinning so that objects of type `derived' are interpreted as
752/// objects of type `base'.
753
754 PyObject* SetTypePinning( PyObject*, PyObject* args )
755 {
756 PyRootClass* derived = nullptr, *base = nullptr;
757 if ( ! PyArg_ParseTuple( args, const_cast< char* >( "O!O!" ),
758 &PyRootType_Type, &derived,
759 &PyRootType_Type, &base ) )
760 return nullptr;
761 gPinnedTypes.push_back( std::make_pair( derived->fCppType, base->fCppType ) );
762
763 Py_RETURN_NONE;
764 }
765
766////////////////////////////////////////////////////////////////////////////////
767/// Add an exception to the type pinning for objects of type `derived'.
768
769 PyObject* IgnoreTypePinning( PyObject*, PyObject* args )
770 {
771 PyRootClass* derived = nullptr;
772 if ( ! PyArg_ParseTuple( args, const_cast< char* >( "O!" ),
773 &PyRootType_Type, &derived ) )
774 return nullptr;
775 gIgnorePinnings.push_back( derived->fCppType );
776
777 Py_RETURN_NONE;
778 }
779
780////////////////////////////////////////////////////////////////////////////////
781/// Cast `obj' to type `type'.
782
783 PyObject* Cast( PyObject*, PyObject* args )
784 {
785 ObjectProxy* obj = nullptr;
786 PyRootClass* type = nullptr;
787 if ( ! PyArg_ParseTuple( args, const_cast< char* >( "O!O!" ),
788 &ObjectProxy_Type, &obj,
789 &PyRootType_Type, &type ) )
790 return nullptr;
791 // TODO: this misses an offset calculation, and reference type must not
792 // be cast ...
793 return BindCppObjectNoCast( obj->GetObject(), type->fCppType,
795 }
796
797} // unnamed namespace
798
799
800//- data -----------------------------------------------------------------------
801static PyMethodDef gPyROOTMethods[] = {
802 { (char*) "CreateScopeProxy", (PyCFunction)PyROOT::CreateScopeProxy,
803 METH_VARARGS, (char*) "PyROOT internal function" },
804 { (char*) "GetCppGlobal", (PyCFunction)PyROOT::GetCppGlobal,
805 METH_VARARGS, (char*) "PyROOT internal function" },
806 { (char*) "LookupCppEntity", (PyCFunction)LookupCppEntity,
807 METH_VARARGS, (char*) "PyROOT internal function" },
808 { (char*) "SetRootLazyLookup", (PyCFunction)SetRootLazyLookup,
809 METH_VARARGS, (char*) "PyROOT internal function" },
810 { (char*) "MakeRootTemplateClass", (PyCFunction)MakeRootTemplateClass,
811 METH_VARARGS, (char*) "PyROOT internal function" },
812 { (char*) "_DestroyPyStrings", (PyCFunction)PyROOT::DestroyPyStrings,
813 METH_NOARGS, (char*) "PyROOT internal function" },
814 { (char*) "_ResetRootModule", (PyCFunction)RootModuleResetCallback,
815 METH_NOARGS, (char*) "PyROOT internal function" },
816 { (char*) "ClearProxiedObjects", (PyCFunction)ClearProxiedObjects,
817 METH_NOARGS, (char*) "PyROOT internal function" },
818 { (char*) "AddressOf", (PyCFunction)AddressOf,
819 METH_VARARGS, (char*) "Retrieve address of held object in a buffer" },
820 { (char*) "addressof", (PyCFunction)addressof,
821 METH_VARARGS, (char*) "Retrieve address of held object as a value" },
822 { (char*) "AsCObject", (PyCFunction)AsCObject,
823 METH_VARARGS, (char*) "Retrieve held object in a CObject" },
824 { (char*) "as_cobject", (PyCFunction)AsCObject,
825 METH_VARARGS, (char*) "Retrieve held object in a CObject" },
826 { (char*) "BindObject", (PyCFunction)BindObject,
827 METH_VARARGS, (char*) "Create an object of given type, from given address" },
828 { (char*) "bind_object", (PyCFunction)BindObject,
829 METH_VARARGS, (char*) "Create an object of given type, from given address" },
830 { (char*) "MakeNullPointer", (PyCFunction)MakeNullPointer,
831 METH_VARARGS, (char*) "Create a NULL pointer of the given type" },
832 { (char*) "_ObjectProxy__expand__", (PyCFunction)ObjectProxyExpand,
833 METH_VARARGS, (char*) "Helper method for pickling" },
834 { (char*) "SetMemoryPolicy", (PyCFunction)SetMemoryPolicy,
835 METH_VARARGS, (char*) "Determines object ownership model" },
836 { (char*) "SetSignalPolicy", (PyCFunction)SetSignalPolicy,
837 METH_VARARGS, (char*) "Trap signals in safe mode to prevent interpreter abort" },
838 { (char*) "SetOwnership", (PyCFunction)SetOwnership,
839 METH_VARARGS, (char*) "Modify held C++ object ownership" },
840 { (char*) "AddSmartPtrType", (PyCFunction)AddSmartPtrType,
841 METH_VARARGS, (char*) "Add a smart pointer to the list of known smart pointer types" },
842 { (char*) "InstallGUIEventInputHook", (PyCFunction)PyROOT::Utility::InstallGUIEventInputHook,
843 METH_NOARGS, (char*) "Install input hook to sent GUI events" },
844 { (char*) "RemoveGUIEventInputHook", (PyCFunction)PyROOT::Utility::RemoveGUIEventInputHook,
845 METH_NOARGS, (char*) "Remove input hook to sent GUI events" },
846 { (char*) "SetTypePinning", (PyCFunction)SetTypePinning,
847 METH_VARARGS, (char*) "Install a type pinning" },
848 { (char*) "IgnoreTypePinning", (PyCFunction)IgnoreTypePinning,
849 METH_VARARGS, (char*) "Don't pin the given type" },
850 { (char*) "Cast", (PyCFunction)Cast,
851 METH_VARARGS, (char*) "Cast the given object to the given type" },
852 { NULL, NULL, 0, NULL }
853};
854
855
856#if PY_VERSION_HEX >= 0x03000000
857struct module_state {
858 PyObject *error;
859};
860
861#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
862
863static int rootmodule_traverse( PyObject* m, visitproc visit, void* arg )
864{
865 Py_VISIT( GETSTATE( m )->error );
866 return 0;
867}
868
869static int rootmodule_clear( PyObject* m )
870{
871 Py_CLEAR( GETSTATE( m )->error );
872 return 0;
873}
874
875
876static struct PyModuleDef moduledef = {
877 PyModuleDef_HEAD_INIT,
878 "libPyROOT",
879 NULL,
880 sizeof(struct module_state),
882 NULL,
883 rootmodule_traverse,
884 rootmodule_clear,
885 NULL
886};
887
888////////////////////////////////////////////////////////////////////////////////
889/// Initialization of extension module libPyROOT.
890
891#define PYROOT_INIT_ERROR return NULL
892extern "C" PyObject* PyInit_libPyROOT()
893#else
894#define PYROOT_INIT_ERROR return
895extern "C" void initlibPyROOT()
896#endif
897{
898 using namespace PyROOT;
899
900// load commonly used python strings
901 if ( ! PyROOT::CreatePyStrings() )
903
904// prepare for lazyness
905 PyObject* dict = PyDict_New();
906#if PY_VERSION_HEX >= 0x03030000
907 gDictLookupOrg = (dict_lookup_func)((PyDictObject*)dict)->ma_keys->dk_lookup;
908#else
909 gDictLookupOrg = (dict_lookup_func)((PyDictObject*)dict)->ma_lookup;
910#endif
911 Py_DECREF( dict );
912
913// setup PyROOT
914#if PY_VERSION_HEX >= 0x03000000
915 gRootModule = PyModule_Create( &moduledef );
916#else
917 gRootModule = Py_InitModule( const_cast< char* >( "libPyROOT" ), gPyROOTMethods );
918#endif
919 if ( ! gRootModule )
921
922// keep gRootModule, but do not increase its reference count even as it is borrowed,
923// or a self-referencing cycle would be created
924
925// Pythonizations ...
926 PyObject* userPythonizations = PyDict_New();
927 PyObject* gblList = PyList_New( 0 );
928 PyDict_SetItemString( userPythonizations, "__global__", gblList );
929 Py_DECREF( gblList );
930 PyModule_AddObject( gRootModule, "UserPythonizations", userPythonizations );
931 PyModule_AddObject( gRootModule, "UserExceptions", PyDict_New() );
932 PyModule_AddObject( gRootModule, "PythonizationScope", PyROOT_PyUnicode_FromString( "__global__" ) );
933
934// inject meta type
935 if ( ! Utility::InitProxy( gRootModule, &PyRootType_Type, "PyRootType" ) )
937
938// inject object proxy type
939 if ( ! Utility::InitProxy( gRootModule, &ObjectProxy_Type, "ObjectProxy" ) )
941
942// inject method proxy type
943 if ( ! Utility::InitProxy( gRootModule, &MethodProxy_Type, "MethodProxy" ) )
945
946// inject template proxy type
947 if ( ! Utility::InitProxy( gRootModule, &TemplateProxy_Type, "TemplateProxy" ) )
949
950// inject property proxy type
951 if ( ! Utility::InitProxy( gRootModule, &PropertyProxy_Type, "PropertyProxy" ) )
953
954// inject custom data types
955 if ( ! Utility::InitProxy( gRootModule, &TCustomFloat_Type, "Double" ) )
957
960
961 if ( ! Utility::InitProxy( gRootModule, &TCustomFloat_Type, "double" ) )
963
966
967 if ( ! Utility::InitProxy( gRootModule, &TCustomInstanceMethod_Type, "InstanceMethod" ) )
969
970 if ( ! Utility::InitProxy( gRootModule, &TTupleOfInstances_Type, "InstancesArray" ) )
972
973 if ( ! Utility::InitProxy( gRootModule, &PyNullPtr_t_Type, "nullptr_t" ) )
975
976// inject identifiable nullptr
978 Py_INCREF( gNullPtrObject );
979 PyModule_AddObject( gRootModule, (char*)"nullptr", gNullPtrObject );
980
981// policy labels
982 PyModule_AddObject( gRootModule, (char*)"kMemoryHeuristics",
983 PyInt_FromLong( (int)TCallContext::kUseHeuristics ) );
984 PyModule_AddObject( gRootModule, (char*)"kMemoryStrict",
985 PyInt_FromLong( (int)TCallContext::kUseStrict ) );
986 PyModule_AddObject( gRootModule, (char*)"kSignalFast",
987 PyInt_FromLong( (int)TCallContext::kFast ) );
988 PyModule_AddObject( gRootModule, (char*)"kSignalSafe",
989 PyInt_FromLong( (int)TCallContext::kSafe ) );
990
991// setup ROOT
993
994// signal policy: don't abort interpreter in interactive mode
995 TCallContext::SetSignalPolicy( gROOT->IsBatch() ? TCallContext::kFast : TCallContext::kSafe );
996
997// inject ROOT namespace for convenience
998 PyModule_AddObject( gRootModule, (char*)"ROOT", CreateScopeProxy( "ROOT" ) );
999
1000#if PY_VERSION_HEX >= 0x03000000
1001 Py_INCREF( gRootModule );
1002 return gRootModule;
1003#endif
1004}
#define Py_TYPE(ob)
Definition: PyROOT.h:166
#define PyBytes_AS_STRING
Definition: PyROOT.h:66
#define PyBytes_FromString
Definition: PyROOT.h:71
int Py_ssize_t
Definition: PyROOT.h:171
#define PY_SSIZE_T_FORMAT
Definition: PyROOT.h:174
#define PyROOT_PyUnicode_Check
Definition: PyROOT.h:76
#define PyROOT_PyUnicode_AsString
Definition: PyROOT.h:78
static void * PyROOT_PyCapsule_GetPointer(PyObject *capsule, const char *)
Definition: PyROOT.h:95
PyDictEntry *(* dict_lookup_func)(PyDictObject *, PyObject *, Long_t)
Definition: PyROOT.h:43
static PyObject * PyROOT_PyCapsule_New(void *cobj, const char *, void(*destr)(void *))
Definition: PyROOT.h:90
#define PyROOT_PyUnicode_FromString
Definition: PyROOT.h:82
#define PyROOT_PyUnicode_FromFormat
Definition: PyROOT.h:81
#define PyBytes_Type
Definition: PyROOT.h:74
#define PyROOT_PyUnicode_Type
Definition: PyROOT.h:88
#define PyBytes_GET_SIZE
Definition: PyROOT.h:68
#define PyROOT_PyUnicode_CheckExact
Definition: PyROOT.h:77
#define PyVarObject_HEAD_INIT(type, size)
Definition: PyROOT.h:164
static RooMathCoreReg dummy
PyObject _PyROOT_NullPtrStruct
Definition: RootModule.cxx:154
static PyObject * nullptr_repr(PyObject *)
Definition: RootModule.cxx:61
#define PYROOT_INIT_ERROR
Definition: RootModule.cxx:894
static PyNumberMethods nullptr_as_number
Definition: RootModule.cxx:76
#define PYROOT_GET_DICT_LOOKUP(mp)
Definition: RootModule.cxx:55
void initlibPyROOT()
Definition: RootModule.cxx:895
static void nullptr_dealloc(PyObject *)
Definition: RootModule.cxx:66
static int nullptr_nonzero(PyObject *)
Definition: RootModule.cxx:71
#define PYROOT_ORGDICT_LOOKUP(mp, key, hash, value_addr)
Definition: RootModule.cxx:303
static PyTypeObject PyNullPtr_t_Type
Definition: RootModule.cxx:120
static PyMethodDef gPyROOTMethods[]
Definition: RootModule.cxx:801
const Bool_t kFALSE
Definition: RtypesCore.h:88
long Long_t
Definition: RtypesCore.h:50
bool Bool_t
Definition: RtypesCore.h:59
const Bool_t kTRUE
Definition: RtypesCore.h:87
@ kIsReference
Definition: TDictionary.h:81
char name[80]
Definition: TGX11.cxx:109
int type
Definition: TGX11.cxx:120
#define pyname
Definition: TMCParticle.cxx:19
_object PyObject
Definition: TPyArg.h:20
#define gROOT
Definition: TROOT.h:415
PyObject_HEAD void * fObject
Definition: ObjectProxy.h:77
void * GetObject() const
Definition: ObjectProxy.h:47
void * GetAddress(ObjectProxy *pyobj)
class attributes, global properties
Type object to hold TClassRef instance (this is only semantically a presentation of PyRootType instan...
Definition: PyRootType.h:37
Cppyy::TCppType_t fCppType
Definition: PyRootType.h:40
The concrete implementation of TBuffer for writing/reading to/from a ROOT file or socket.
Definition: TBufferFile.h:46
void * ReadObjectAny(const TClass *cast) override
Read object from I/O buffer.
void WriteFastArray(const Bool_t *b, Int_t n) override
Write array of n bools into the I/O buffer.
@ kWrite
Definition: TBuffer.h:72
@ kRead
Definition: TBuffer.h:72
Mother of all ROOT objects.
Definition: TObject.h:37
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:357
void AddSmartPtrType(const std::string &)
Definition: Cppyy.cxx:631
TCppScope_t gGlobalScope
Definition: Cppyy.cxx:64
TCppScope_t TCppType_t
Definition: Cppyy.h:16
long long GetEnumDataValue(TCppEnum_t, TCppIndex_t idata)
Definition: Cppyy.cxx:1124
Bool_t IsEnum(const std::string &type_name)
Definition: Cppyy.cxx:579
std::string GetEnumDataName(TCppEnum_t, TCppIndex_t idata)
Definition: Cppyy.cxx:1119
void * TCppEnum_t
Definition: Cppyy.h:19
Long_t TCppIndex_t
Definition: Cppyy.h:21
TCppScope_t GetScope(const std::string &scope_name)
Definition: Cppyy.cxx:197
TCppEnum_t GetEnum(TCppScope_t scope, const std::string &enum_name)
Definition: Cppyy.cxx:1102
TCppIndex_t GetNumEnumData(TCppEnum_t)
Definition: Cppyy.cxx:1114
R__EXTERN PyObject * gClass
Definition: PyStrings.h:18
R__EXTERN PyObject * gName
Definition: PyStrings.h:33
R__EXTERN PyObject * gDict
Definition: PyStrings.h:22
R__EXTERN PyObject * gCppNameNew
Definition: PyStrings.h:35
R__EXTERN PyObject * gCppName
Definition: PyStrings.h:34
PyObject * RemoveGUIEventInputHook()
Definition: Utility.cxx:973
Bool_t InitProxy(PyObject *module, PyTypeObject *pytype, const char *name)
Initialize a proxy class for use by python, and add it to the ROOT module.
Definition: Utility.cxx:542
PyObject * InstallGUIEventInputHook()
Definition: Utility.cxx:960
int GetBuffer(PyObject *pyobject, char tc, int size, void *&buf, Bool_t check=kTRUE)
Retrieve a linear buffer pointer from the given pyobject.
Definition: Utility.cxx:562
PyObject * BuildTemplateName(PyObject *pyname, PyObject *tpArgs, int argoff, PyObject *args=nullptr, ArgPreference=kNone, int *pcnt=nullptr, bool inferredTypes=false)
Helper to construct the "< type, type, ... >" part of a templated name (either for a class as in Make...
Definition: Utility.cxx:463
PyObject * BindCppObject(Cppyy::TCppObject_t object, Cppyy::TCppType_t klass, Bool_t isRef=kFALSE)
if the object is a null pointer, return a typed one (as needed for overloading)
PyTypeObject PyRootType_Type
Definition: PyRootType.cxx:233
R__EXTERN dict_lookup_func gDictLookupOrg
Definition: Utility.h:15
Bool_t ObjectProxy_Check(T *object)
Definition: ObjectProxy.h:91
void InitRoot()
Bool_t CreatePyStrings()
Definition: PyStrings.cxx:62
PyObject * DestroyPyStrings()
Remove all cached python strings.
Definition: PyStrings.cxx:118
PyTypeObject ObjectProxy_Type
PyTypeObject TCustomInstanceMethod_Type
PyObject * CreateScopeProxy(Cppyy::TCppScope_t)
Convenience function with a lookup first through the known existing proxies.
R__EXTERN Bool_t gDictLookupActive
Definition: Utility.h:18
PyTypeObject TemplateProxy_Type
std::vector< Cppyy::TCppType_t > gIgnorePinnings
Definition: RootModule.cxx:163
PyTypeObject TTupleOfInstances_Type
Representation of C-style array of instances.
Bool_t PropertyProxy_CheckExact(T *object)
Definition: PropertyProxy.h:56
std::vector< std::pair< Cppyy::TCppType_t, Cppyy::TCppType_t > > gPinnedTypes
Definition: RootModule.cxx:162
PyTypeObject MethodProxy_Type
R__EXTERN PyObject * gNullPtrObject
Definition: Converters.cxx:40
PyTypeObject TCustomInt_Type
R__EXTERN PyObject * gRootModule
Definition: ObjectProxy.cxx:39
PyTypeObject TCustomFloat_Type
Custom builtins, detectable by type, for pass by ref.
PyObject * GetCppGlobal(const std::string &name)
try named global variable/enum (first ROOT, then Cling: sync is too slow)
PyObject * BindCppObjectNoCast(Cppyy::TCppObject_t object, Cppyy::TCppType_t klass, Bool_t isRef=kFALSE, Bool_t isValue=kFALSE)
only known or knowable objects will be bound (null object is ok)
Bool_t PropertyProxy_Check(T *object)
Definition: PropertyProxy.h:50
PyTypeObject PropertyProxy_Type
PyObject * ClearProxiedObjects()
Delete all memory-regulated objects.
auto * m
Definition: textangle.C:8
auto * l
Definition: textangle.C:4