Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
PyROOTModule.cxx
Go to the documentation of this file.
1// Author: Enric Tejedor CERN 06/2018
2// Original PyROOT code by Wim Lavrijsen, LBL
3
4/*************************************************************************
5 * Copyright (C) 1995-2018, 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 "PyROOTPythonize.h"
14#include "RPyROOTApplication.h"
15
16// Cppyy
17#include "CPyCppyy/API.h"
18
19// ROOT
20#include "TInterpreter.h"
21#include "TROOT.h"
22#include "TSystem.h"
23#include "RConfigure.h"
24
25// Standard
26#include <any>
27#include <string>
28#include <sstream>
29#include <utility>
30#include <vector>
31
32#include "IOHandler.cxx"
33
34namespace PyROOT {
35
37
39{
40 PyObject *name = nullptr;
41 PyObject *target = nullptr;
42
43 if (!PyArg_ParseTuple(args, "UU:RegisterConverterAlias", &name, &target)) {
44 return nullptr;
45 }
46
47 const char *nameStr = PyUnicode_AsUTF8AndSize(name, nullptr);
48 if (!nameStr) {
49 return nullptr;
50 }
51
52 const char *targetStr = PyUnicode_AsUTF8AndSize(target, nullptr);
53 if (!targetStr) {
54 return nullptr;
55 }
56
58
60}
61
63{
64 PyObject *name = nullptr;
65 PyObject *target = nullptr;
66
67 if (!PyArg_ParseTuple(args, "UU:RegisterExecutorAlias", &name, &target)) {
68 return nullptr;
69 }
70
71 const char *nameStr = PyUnicode_AsUTF8AndSize(name, nullptr);
72 if (!nameStr) {
73 return nullptr;
74 }
75
76 const char *targetStr = PyUnicode_AsUTF8AndSize(target, nullptr);
77 if (!targetStr) {
78 return nullptr;
79 }
80
82
84}
85
86/// \brief A PyObject wrapper to track reference counting of external objects
87///
88/// This wrapper can be useful in shared ownership scenarios when a C++ object
89/// is created on the Python side and there is no easy way to track its ownership
90/// on the C++ side. If multiple instances of this class are given the same
91/// Python proxy, they will increase/decrease its reference counting following
92/// Python rules and ensure proper destruction of the underlying C++ object when
93/// no other Python objects are referencing it.
95 PyObject *fObject{nullptr};
96
97 void Reset(PyObject *object)
98 {
99 if (fObject) {
101 fObject = nullptr;
102 }
103 if (object) {
104 Py_INCREF(object);
105 fObject = object;
106 }
107 }
108
109public:
110 PyObjRefCounter(PyObject *object) { Reset(object); }
111
112 ~PyObjRefCounter() { Reset(nullptr); }
113
115
117 {
118 Reset(other.fObject);
119 return *this;
120 }
121
123 {
124 fObject = other.fObject;
125 other.fObject = nullptr;
126 }
127
129 {
130 fObject = other.fObject;
131 other.fObject = nullptr;
132 return *this;
133 }
134};
135
137{
138 PyObject *object = nullptr;
139
140 PyArg_ParseTuple(args, "O:PyObjRefCounterAsStdAny", &object);
141
142 // The std::any is managed by Python
143 return CPyCppyy::Instance_FromVoidPtr(new std::any{std::in_place_type<PyObjRefCounter>, object}, "std::any",
144 /*python_owns=*/true);
145}
146
147// Helper function to get the pointer to a buffer (heavily simplified copy of
148// CPyCppyy::Utility::GetBuffer).
149void GetBuffer(PyObject *pyobject, void *&buf)
150{
151 buf = nullptr;
152
153 // Exclude text-like objects (policy decision)
155 return;
156
157 // Fast path: bytearray
160 return;
161 }
162
163 // Buffer protocol
165 // Avoid potential issues with empty sequences
167 return;
168
169 Py_buffer view;
170 if (PyObject_GetBuffer(pyobject, &view, PyBUF_SIMPLE) == 0) {
171 if (view.buf && view.len > 0)
172 buf = view.buf;
173 PyBuffer_Release(&view);
174 } else {
175 PyErr_Clear();
176 }
177 }
178}
179
180} // namespace PyROOT
181
182// Methods offered by the interface
184 {"AddCPPInstancePickling", (PyCFunction)PyROOT::AddCPPInstancePickling, METH_NOARGS,
185 "Add a custom pickling mechanism for Cppyy Python proxy objects"},
187 "Allow to access branches as tree attributes"},
188 {"AddTClassDynamicCastPyz", (PyCFunction)PyROOT::AddTClassDynamicCastPyz, METH_VARARGS,
189 "Cast the void* returned by TClass::DynamicCast to the right type"},
191 "Fully enable the use of TTree::Branch from Python"},
192 {"AddPrettyPrintingPyz", (PyCFunction)PyROOT::AddPrettyPrintingPyz, METH_VARARGS,
193 "Add pretty printing pythonization"},
195 "Initialize interactive ROOT use from Python"},
197 "Install an input hook to process GUI events"},
198 {"_CPPInstance__expand__", (PyCFunction)PyROOT::CPPInstanceExpand, METH_VARARGS,
199 "Deserialize a pickled object"},
200 {"JupyROOTExecutor", (PyCFunction)JupyROOTExecutor, METH_VARARGS, "Create JupyROOTExecutor"},
201 {"JupyROOTDeclarer", (PyCFunction)JupyROOTDeclarer, METH_VARARGS, "Create JupyROOTDeclarer"},
202 {"JupyROOTExecutorHandler_Clear", (PyCFunction)JupyROOTExecutorHandler_Clear, METH_NOARGS,
203 "Clear JupyROOTExecutorHandler"},
204 {"JupyROOTExecutorHandler_Ctor", (PyCFunction)JupyROOTExecutorHandler_Ctor, METH_NOARGS,
205 "Create JupyROOTExecutorHandler"},
206 {"JupyROOTExecutorHandler_Poll", (PyCFunction)JupyROOTExecutorHandler_Poll, METH_NOARGS,
207 "Poll JupyROOTExecutorHandler"},
208 {"JupyROOTExecutorHandler_EndCapture", (PyCFunction)JupyROOTExecutorHandler_EndCapture, METH_NOARGS,
209 "End capture JupyROOTExecutorHandler"},
210 {"JupyROOTExecutorHandler_InitCapture", (PyCFunction)JupyROOTExecutorHandler_InitCapture, METH_NOARGS,
211 "Init capture JupyROOTExecutorHandler"},
212 {"JupyROOTExecutorHandler_GetStdout", (PyCFunction)JupyROOTExecutorHandler_GetStdout, METH_NOARGS,
213 "Get stdout JupyROOTExecutorHandler"},
214 {"JupyROOTExecutorHandler_GetStderr", (PyCFunction)JupyROOTExecutorHandler_GetStderr, METH_NOARGS,
215 "Get stderr JupyROOTExecutorHandler"},
216 {"JupyROOTExecutorHandler_Dtor", (PyCFunction)JupyROOTExecutorHandler_Dtor, METH_NOARGS,
217 "Destruct JupyROOTExecutorHandler"},
218 {"CPyCppyyRegisterConverterAlias", (PyCFunction)PyROOT::RegisterConverterAlias, METH_VARARGS,
219 "Register a custom converter that is a reference to an existing converter"},
220 {"CPyCppyyRegisterExecutorAlias", (PyCFunction)PyROOT::RegisterExecutorAlias, METH_VARARGS,
221 "Register a custom executor that is a reference to an existing executor"},
222 {"PyObjRefCounterAsStdAny", (PyCFunction)PyROOT::PyObjRefCounterAsStdAny, METH_VARARGS,
223 "Wrap a reference count to any Python object in a std::any for resource management in C++"},
224 {NULL, NULL, 0, NULL}};
225
229
230#define GETSTATE(m) ((struct module_state *)PyModule_GetState(m))
231
233{
234 Py_VISIT(GETSTATE(m)->error);
235 return 0;
236}
237
239{
240 Py_CLEAR(GETSTATE(m)->error);
241 return 0;
242}
243
244static struct PyModuleDef moduledef = {PyModuleDef_HEAD_INIT, "libROOTPythonizations", NULL,
245 sizeof(struct module_state), gPyROOTMethods, NULL,
247
248/// Initialization of extension module libROOTPythonizations
249
251{
252 using namespace PyROOT;
253
254 // setup PyROOT
255 gRootModule = PyModule_Create(&moduledef);
256 if (!gRootModule)
257 return nullptr;
258
259 // keep gRootModule, but do not increase its reference count even as it is borrowed,
260 // or a self-referencing cycle would be created
261
262 return gRootModule;
263}
#define PyBytes_Check
Definition CPyCppyy.h:61
#define Py_RETURN_NONE
Definition CPyCppyy.h:268
PyObject * JupyROOTExecutorHandler_Ctor(PyObject *, PyObject *)
PyObject * JupyROOTDeclarer(PyObject *, PyObject *args)
PyObject * JupyROOTExecutorHandler_GetStdout(PyObject *, PyObject *)
PyObject * JupyROOTExecutor(PyObject *, PyObject *args)
PyObject * JupyROOTExecutorHandler_EndCapture(PyObject *, PyObject *)
PyObject * JupyROOTExecutorHandler_Poll(PyObject *, PyObject *)
PyObject * JupyROOTExecutorHandler_Clear(PyObject *, PyObject *)
PyObject * JupyROOTExecutorHandler_GetStderr(PyObject *, PyObject *)
PyObject * JupyROOTExecutorHandler_InitCapture(PyObject *, PyObject *)
PyObject * JupyROOTExecutorHandler_Dtor(PyObject *, PyObject *)
_object PyObject
static struct PyModuleDef moduledef
#define GETSTATE(m)
PyObject * PyInit_libROOTPythonizations()
Initialization of extension module libROOTPythonizations.
static int rootmodule_clear(PyObject *m)
static int rootmodule_traverse(PyObject *m, visitproc visit, void *arg)
static PyMethodDef gPyROOTMethods[]
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t target
char name[80]
Definition TGX11.cxx:157
A PyObject wrapper to track reference counting of external objects.
PyObjRefCounter(PyObject *object)
PyObjRefCounter & operator=(PyObjRefCounter &&other)
void Reset(PyObject *object)
PyObjRefCounter(const PyObjRefCounter &other)
PyObjRefCounter(PyObjRefCounter &&other)
PyObjRefCounter & operator=(const PyObjRefCounter &other)
static PyObject * InstallGUIEventInputHook(PyObject *self, PyObject *args)
Install a method hook for sending events to the GUI.
static PyObject * InitApplication(PyObject *self, PyObject *args)
Initialize an RPyROOTApplication.
CPYCPPYY_EXTERN bool RegisterExecutorAlias(const std::string &name, const std::string &target)
CPYCPPYY_EXTERN PyObject * Instance_FromVoidPtr(void *addr, const std::string &classname, bool python_owns=false)
Definition API.cxx:133
CPYCPPYY_EXTERN bool RegisterConverterAlias(const std::string &name, const std::string &target)
PyObject * PyObjRefCounterAsStdAny(PyObject *, PyObject *args)
PyObject * BranchPyz(PyObject *self, PyObject *args)
Add pythonization for TTree::Branch.
Definition TTreePyz.cxx:385
PyObject * AddCPPInstancePickling(PyObject *self, PyObject *args)
Set reduce attribute for CPPInstance objects.
void GetBuffer(PyObject *pyobject, void *&buf)
PyObject * CPPInstanceExpand(PyObject *self, PyObject *args)
Deserialize pickled objects.
PyObject * gRootModule
PyObject * AddTClassDynamicCastPyz(PyObject *self, PyObject *args)
Add pythonization for TClass::DynamicCast.
Definition TClassPyz.cxx:77
PyObject * RegisterExecutorAlias(PyObject *, PyObject *args)
PyObject * GetBranchAttr(PyObject *self, PyObject *args)
Definition TTreePyz.cxx:179
PyObject * RegisterConverterAlias(PyObject *, PyObject *args)
PyObject * AddPrettyPrintingPyz(PyObject *self, PyObject *args)
Add pretty printing pythonization.
PyObject * error
TMarker m
Definition textangle.C:8