ATLAS Offline Software
Utility.cxx
Go to the documentation of this file.
1 // This file's extension implies that it's C, but it's really -*- C++ -*-.
2 /*
3  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
4 */
13 // Called from python, so only excuted single-threaded (GIL).
16 
17 
18 #include "Utility.h"
19 #include "TInterpreter.h"
20 #include <sstream>
21 
22 
23 namespace RootUtils {
24 
25 
26 int GetBuffer( PyObject* pyobject, char tc, int size, void*& buf, Bool_t check )
27 {
28 // Retrieve a linear buffer pointer from the given pyobject.
29 
30 // special case: don't handle character strings here (yes, they're buffers, but not quite)
31  if ( PyBytes_Check( pyobject ) )
32  return 0;
33 
34 // attempt to retrieve pointer to buffer interface
35  PyBufferProcs* bufprocs = Py_TYPE(pyobject)->tp_as_buffer;
36 
37  PySequenceMethods* seqmeths = Py_TYPE(pyobject)->tp_as_sequence;
38  if ( seqmeths != 0 && bufprocs != 0
39  && bufprocs->bf_getbuffer != 0
40  ) {
41 
42  // get the buffer
43  Py_buffer bufinfo;
44  (*(bufprocs->bf_getbuffer))( pyobject, &bufinfo, PyBUF_WRITABLE );
45  buf = (char*)bufinfo.buf;
46  Py_ssize_t buflen = bufinfo.len;
47 
48  if ( buf && check == kTRUE ) {
49  // determine buffer compatibility (use "buf" as a status flag)
50  PyObject* pytc = PyObject_GetAttrString( pyobject, "typecode");
51  if ( pytc != 0 ) { // for array objects
52  const char* s = PyUnicode_AsUTF8AndSize( pytc, nullptr );
53  if ( s && s[0] != tc )
54  buf = 0; // no match
55  Py_DECREF( pytc );
56  } else if ( seqmeths->sq_length &&
57  (int)(buflen / (*(seqmeths->sq_length))( pyobject )) == size ) {
58  // this is a gamble ... may or may not be ok, but that's for the user
59  PyErr_Clear();
60  } else if ( buflen == size ) {
61  // also a gamble, but at least 1 item will fit into the buffer, so very likely ok ...
62  PyErr_Clear();
63  } else {
64  buf = 0; // not compatible
65 
66  // clarify error message
67  PyObject* pytype = 0, *pyvalue = 0, *pytrace = 0;
68  PyErr_Fetch( &pytype, &pyvalue, &pytrace );
69  const char* s = PyUnicode_AsUTF8AndSize( pyvalue, nullptr );
70  if (!s) s = "(null)";
71  PyObject* pyvalue2 = PyUnicode_FromFormat(
72  (char*)"%s and given element size (%ld) do not match needed (%d)",
73  s,
74  seqmeths->sq_length ? (Long_t)(buflen / (*(seqmeths->sq_length))( pyobject )) : (Long_t)buflen,
75  size );
76  Py_DECREF( pyvalue );
77  PyErr_Restore( pytype, pyvalue2, pytrace );
78  }
79  }
80 
81  return buflen;
82  }
83 
84  return 0;
85 }
86 
87 
88 //- public functions ---------------------------------------------------------
90 {
91  return PyImport_ImportModule ("ROOT");
92 }
93 
94 
96 {
97  static PyObject* const rootModule = getRootModule();
98  Py_INCREF (rootModule);
99  return rootModule;
100 }
101 
102 
104 {
105  TClass* cls = nullptr;
106  PyObject* attr = PyObject_GetAttrString ((PyObject*)Py_TYPE(obj), "__cpp_name__");
107  if (attr) {
108  PyObject* buf = PyUnicode_AsASCIIString (attr);
109  if (buf) {
110  char* s = PyBytes_AsString (buf);
111  if (*s == '<') ++s;
112  if (strncmp (s, "ROOT.", 5) == 0)
113  s += 5;
114  if (strncmp (s, "cppyy.gbl.", 10) == 0)
115  s += 10;
116  cls = TClass::GetClass (s);
117  Py_DECREF(buf);
118  }
119  Py_DECREF(attr);
120  }
121  PyErr_Clear();
122  return cls;
123 }
124 
125 
127 {
128  PyObject* root = rootModule();
129  PyObject* ret = PyObject_GetAttrString (root, "SetOwnership");
130  Py_DECREF (root);
131  return ret;
132 }
133 
135 {
136  static PyObject* const func = getSetOwnershipFunc();
137  Py_INCREF (func);
138  return func;
139 }
140 
142 {
143  PyObject* func = setOwnershipFunc();
144  PyObject* ret = PyObject_CallFunction (func, const_cast<char*>("OI"),
145  obj,
146  static_cast<unsigned int>(flag));
147  Py_DECREF (func);
148  if (ret) {
149  Py_DECREF (ret);
150  return true;
151  }
152  return false;
153 }
154 
155 
156 } // namespace RootUtils
RootUtils
Definition: ILogger.h:20
python.SystemOfUnits.s
int s
Definition: SystemOfUnits.py:131
Utility.h
Utility code originally from pyroot.
CaloClusterListBadChannel.cls
cls
Definition: CaloClusterListBadChannel.py:8
RootUtils::getSetOwnershipFunc
PyObject * getSetOwnershipFunc()
Definition: Utility.cxx:126
sendEI_SPB.root
root
Definition: sendEI_SPB.py:34
python.setupRTTAlg.size
int size
Definition: setupRTTAlg.py:39
RootUtils::objectIsA
TClass * objectIsA(PyObject *obj)
Definition: Utility.cxx:103
ret
T ret(T t)
Definition: rootspy.cxx:260
master.flag
bool flag
Definition: master.py:29
RootUtils::rootModule
PyObject * rootModule()
Definition: Utility.cxx:95
RootUtils::setOwnershipFunc
PyObject * setOwnershipFunc()
Definition: Utility.cxx:134
RootUtils::getRootModule
PyObject * getRootModule()
Definition: Utility.cxx:89
LArNewCalib_Delay_OFC_Cali.check
check
Definition: LArNewCalib_Delay_OFC_Cali.py:208
if
if(febId1==febId2)
Definition: LArRodBlockPhysicsV0.cxx:569
RootUtils::setOwnership
bool setOwnership(PyObject *obj, bool flag)
Definition: Utility.cxx:141
RootUtils::GetBuffer
int GetBuffer(PyObject *pyobject, char tc, int size, void *&buf, Bool_t check)
Definition: Utility.cxx:26
ATLAS_NO_CHECK_FILE_THREAD_SAFETY
ATLAS_NO_CHECK_FILE_THREAD_SAFETY
Definition: Utility.cxx:15
checker_macros.h
Define macros for attributes used to control the static checker.
python.PyAthena.obj
obj
Definition: PyAthena.py:135
PyObject
_object PyObject
Definition: IPyComponent.h:26