Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TPyDispatcher.cxx
Go to the documentation of this file.
1 // Author: Wim Lavrijsen, Aug 2007
2 
3 // Bindings
4 #include "PyROOT.h"
5 #include "TPyDispatcher.h"
6 #include "RootWrapper.h"
7 
8 // ROOT
9 #include "TClass.h"
10 #include "TObject.h"
11 
12 // Standard
13 #include <stdarg.h>
14 
15 
16 //______________________________________________________________________________
17 // Python callback dispatcher
18 // ==========================
19 //
20 // The TPyDispatcher class acts as a functor that can be used for TFn's and GUIs
21 // to install callbacks from CINT.
22 
23 
24 //- data ---------------------------------------------------------------------
25 ClassImp(TPyDispatcher);
26 
27 
28 //- constructors/destructor --------------------------------------------------
29 TPyDispatcher::TPyDispatcher( PyObject* callable ) : fCallable( 0 )
30 {
31 // Construct a TPyDispatcher from a callable python object. Applies python
32 // object reference counting.
33  Py_XINCREF( callable );
34  fCallable = callable;
35 }
36 
37 ////////////////////////////////////////////////////////////////////////////////
38 /// Copy constructor. Applies python object reference counting.
39 
40 TPyDispatcher::TPyDispatcher( const TPyDispatcher& other ) : TObject ( other )
41 {
42  Py_XINCREF( other.fCallable );
43  fCallable = other.fCallable;
44 }
45 
46 ////////////////////////////////////////////////////////////////////////////////
47 /// Assignment operator. Applies python object reference counting.
48 
49 TPyDispatcher& TPyDispatcher::operator=( const TPyDispatcher& other )
50 {
51  if ( this != &other ) {
52  this->TObject::operator=( other );
53 
54  Py_XDECREF( fCallable );
55  Py_XINCREF( other.fCallable );
56  fCallable = other.fCallable;
57  }
58 
59  return *this;
60 }
61 
62 ////////////////////////////////////////////////////////////////////////////////
63 /// Destructor. Reference counting for the held python object is in effect.
64 
65 TPyDispatcher::~TPyDispatcher() {
66  Py_XDECREF( fCallable );
67 }
68 
69 
70 //- public members -----------------------------------------------------------
71 PyObject* TPyDispatcher::DispatchVA( const char* format, ... )
72 {
73 // Dispatch the arguments to the held callable python object, using format to
74 // interpret the types of the arguments. Note that format is in python style,
75 // not in C printf style. See: https://docs.python.org/2/c-api/arg.html .
76  PyObject* args = 0;
77 
78  if ( format ) {
79  va_list va;
80  va_start( va, format );
81 
82  args = Py_VaBuildValue( (char*)format, va );
83 
84  va_end( va );
85 
86  if ( ! args ) {
87  PyErr_Print();
88  return 0;
89  }
90 
91  if ( ! PyTuple_Check( args ) ) { // if only one arg ...
92  PyObject* t = PyTuple_New( 1 );
93  PyTuple_SET_ITEM( t, 0, args );
94  args = t;
95  }
96 
97  }
98 
99  PyObject* result = PyObject_CallObject( fCallable, args );
100  Py_XDECREF( args );
101 
102  if ( ! result ) {
103  PyErr_Print();
104  return 0;
105  }
106 
107  return result;
108 }
109 
110 ////////////////////////////////////////////////////////////////////////////////
111 
112 PyObject* TPyDispatcher::DispatchVA1( const char* clname, void* obj, const char* format, ... )
113 {
114  PyObject* pyobj = PyROOT::BindCppObject( obj, Cppyy::GetScope( clname ), kFALSE /* isRef */ );
115  if ( ! pyobj ) {
116  PyErr_Print();
117  return 0;
118  }
119 
120  PyObject* args = 0;
121 
122  if ( format ) {
123  va_list va;
124  va_start( va, format );
125 
126  args = Py_VaBuildValue( (char*)format, va );
127 
128  va_end( va );
129 
130  if ( ! args ) {
131  PyErr_Print();
132  return 0;
133  }
134 
135  if ( ! PyTuple_Check( args ) ) { // if only one arg ...
136  PyObject* t = PyTuple_New( 2 );
137  PyTuple_SET_ITEM( t, 0, pyobj );
138  PyTuple_SET_ITEM( t, 1, args );
139  args = t;
140  } else {
141  PyObject* t = PyTuple_New( PyTuple_GET_SIZE( args ) + 1 );
142  PyTuple_SET_ITEM( t, 0, pyobj );
143  for ( int i = 0; i < PyTuple_GET_SIZE( args ); i++ ) {
144  PyObject* item = PyTuple_GET_ITEM( args, i );
145  Py_INCREF( item );
146  PyTuple_SET_ITEM( t, i+1, item );
147  }
148  Py_DECREF( args );
149  args = t;
150  }
151  } else {
152  args = PyTuple_New( 1 );
153  PyTuple_SET_ITEM( args, 0, pyobj );
154  }
155 
156  PyObject* result = PyObject_CallObject( fCallable, args );
157  Py_XDECREF( args );
158 
159  if ( ! result ) {
160  PyErr_Print();
161  return 0;
162  }
163 
164  return result;
165 }
166 
167 ////////////////////////////////////////////////////////////////////////////////
168 
169 PyObject* TPyDispatcher::Dispatch( TPad* selpad, TObject* selected, Int_t event )
170 {
171  PyObject* args = PyTuple_New( 3 );
172  PyTuple_SET_ITEM( args, 0, PyROOT::BindCppObject( selpad, Cppyy::GetScope( "TPad" ) ) );
173  PyTuple_SET_ITEM( args, 1, PyROOT::BindCppObject( selected, Cppyy::GetScope( "TObject" ) ) );
174  PyTuple_SET_ITEM( args, 2, PyInt_FromLong( event ) );
175 
176  PyObject* result = PyObject_CallObject( fCallable, args );
177  Py_XDECREF( args );
178 
179  if ( ! result ) {
180  PyErr_Print();
181  return 0;
182  }
183 
184  return result;
185 }
186 
187 ////////////////////////////////////////////////////////////////////////////////
188 
189 PyObject* TPyDispatcher::Dispatch( Int_t event, Int_t x, Int_t y, TObject* selected )
190 {
191  PyObject* args = PyTuple_New( 4 );
192  PyTuple_SET_ITEM( args, 0, PyInt_FromLong( event ) );
193  PyTuple_SET_ITEM( args, 1, PyInt_FromLong( x ) );
194  PyTuple_SET_ITEM( args, 2, PyInt_FromLong( y ) );
195  PyTuple_SET_ITEM( args, 3, PyROOT::BindCppObject( selected, Cppyy::GetScope( "TObject" ) ) );
196 
197  PyObject* result = PyObject_CallObject( fCallable, args );
198  Py_XDECREF( args );
199 
200  if ( ! result ) {
201  PyErr_Print();
202  return 0;
203  }
204 
205  return result;
206 }
207 
208 ////////////////////////////////////////////////////////////////////////////////
209 
210 PyObject* TPyDispatcher::Dispatch( TVirtualPad* pad, TObject* obj, Int_t event )
211 {
212  PyObject* args = PyTuple_New( 3 );
213  PyTuple_SET_ITEM( args, 0, PyROOT::BindCppObject( pad, Cppyy::GetScope( "TVirtualPad" ) ) );
214  PyTuple_SET_ITEM( args, 1, PyROOT::BindCppObject( obj, Cppyy::GetScope( "TObject" ) ) );
215  PyTuple_SET_ITEM( args, 2, PyInt_FromLong( event ) );
216 
217  PyObject* result = PyObject_CallObject( fCallable, args );
218  Py_XDECREF( args );
219 
220  if ( ! result ) {
221  PyErr_Print();
222  return 0;
223  }
224 
225  return result;
226 }
227 
228 ////////////////////////////////////////////////////////////////////////////////
229 
230 PyObject* TPyDispatcher::Dispatch( TGListTreeItem* item, TDNDData* data )
231 {
232  PyObject* args = PyTuple_New( 2 );
233  PyTuple_SET_ITEM( args, 0, PyROOT::BindCppObject( item, Cppyy::GetScope( "TGListTreeItem" ) ) );
234  PyTuple_SET_ITEM( args, 1, PyROOT::BindCppObject( data, Cppyy::GetScope( "TDNDData" ) ) );
235 
236  PyObject* result = PyObject_CallObject( fCallable, args );
237  Py_XDECREF( args );
238 
239  if ( ! result ) {
240  PyErr_Print();
241  return 0;
242  }
243 
244  return result;
245 }
246 
247 ////////////////////////////////////////////////////////////////////////////////
248 
249 PyObject* TPyDispatcher::Dispatch( const char* name, const TList* attr )
250 {
251  PyObject* args = PyTuple_New( 2 );
252  PyTuple_SET_ITEM( args, 0, PyBytes_FromString( name ) );
253  PyTuple_SET_ITEM( args, 1, PyROOT::BindCppObject( (void*)attr, Cppyy::GetScope( "TList" ) ) );
254 
255  PyObject* result = PyObject_CallObject( fCallable, args );
256  Py_XDECREF( args );
257 
258  if ( ! result ) {
259  PyErr_Print();
260  return 0;
261  }
262 
263  return result;
264 }
265 
266 ////////////////////////////////////////////////////////////////////////////////
267 
268 PyObject* TPyDispatcher::Dispatch( TSlave* slave, TProofProgressInfo* pi )
269 {
270  PyObject* args = PyTuple_New( 2 );
271  PyTuple_SET_ITEM( args, 0, PyROOT::BindCppObject( slave, Cppyy::GetScope( "TSlave" ) ) );
272  PyTuple_SET_ITEM( args, 1, PyROOT::BindCppObject( pi, Cppyy::GetScope( "TProofProgressInfo" ) ) );
273 
274  PyObject* result = PyObject_CallObject( fCallable, args );
275  Py_XDECREF( args );
276 
277  if ( ! result ) {
278  PyErr_Print();
279  return 0;
280  }
281 
282  return result;
283 }