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