ATLAS Offline Software
Toggle main menu visibility
Loading...
Searching...
No Matches
Control
StoreGateBindings
src
SgPyDataModel.cxx
Go to the documentation of this file.
1
/*
2
Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3
*/
4
5
6
#include "
SgPyDataModel.h
"
7
#include "GaudiKernel/ServiceHandle.h"
8
9
// Called from python, so only excuted single-threaded (GIL).
10
#include "
CxxUtils/checker_macros.h
"
11
ATLAS_NO_CHECK_FILE_THREAD_SAFETY
;
12
13
const
CLID
PyCLID
= 72785480;
14
15
namespace
{
16
17
18
TClass* objectIsA (
PyObject
* obj)
19
{
20
TClass* cls =
nullptr
;
21
PyObject
* attr = PyObject_GetAttrString ((
PyObject
*)Py_TYPE(obj),
"__cpp_name__"
);
22
if
(attr) {
23
const
char
* s = PyUnicode_AsUTF8AndSize (attr,
nullptr
);
24
if
(s) {
25
if
(*s ==
'<'
) ++s;
26
if
(strncmp (s,
"ROOT."
, 5) == 0)
27
s += 5;
28
if
(strncmp (s,
"cppyy.gbl."
, 10) == 0)
29
s += 10;
30
cls = TClass::GetClass (s);
31
}
32
Py_XDECREF (attr);
33
}
34
PyErr_Clear();
35
return
cls;
36
}
37
38
39
}
40
41
namespace
SG
{
42
43
PyDataBucket::PyDataBucket
(
PyObject
* pyObj,
44
CLID
clid ) :
45
DataBucketBase
(),
46
m_pyObj
( pyObj ),
47
m_clid
( clid ),
48
m_bib
(
SG
::
BaseInfoBase
::
find
(clid) )
49
{
50
// prevent Python from sweeping the rug under our feet
51
Py_INCREF( pyObj );
52
}
53
54
void
*
PyDataBucket::cast
(
CLID
clid,
55
IRegisterTransient
*
/*itr*/
,
56
bool
/*isConst*/
)
57
{
58
RootUtils::PyGILStateEnsure
gil;
59
// if requested type is same than myself ==> no conversion needed
60
if
( clid ==
m_clid
) {
61
return
clid ==
PyCLID
62
?
m_pyObj
63
:
CPPInstance_ASVOIDPTR
(
m_pyObj
);
64
}
65
void
* address = (
m_clid
==
PyCLID
)
66
? (
void
*)
m_pyObj
67
:
CPPInstance_ASVOIDPTR
(
m_pyObj
);
68
69
// try SG-based conversion functions
70
{
71
void
* o =
m_bib
?
m_bib
->cast(address, clid) : 0;
72
if
( o ) {
return
o; }
73
}
74
75
// try PyRoot based ones
76
PyObject
* pytp =
PyProxyMgr::instance
().
pytp
(clid);
77
if
( !pytp ) {
78
PyErr_Format( PyExc_TypeError,
"actual type of CLID %lu unknown"
,
79
(
long
unsigned
int
)clid );
80
return
0;
81
}
82
83
// this will be a conversion for a class instance only (see below:
84
// verified that only a CPPInstance is expected), so bind with cast
85
std::string pytpstr =
RootUtils::PyGetString
(pytp).first;
86
TClass* cls = TClass::GetClass (pytpstr.c_str());
87
if
(!cls) {
88
PyErr_Format( PyExc_TypeError,
"Can't find TClass for `%s'"
,
89
pytpstr.c_str() );
90
return
0;
91
}
92
TClass* act_class = cls->GetActualClass (address);
93
PyObject
* value = TPython::CPPInstance_FromVoidPtr (address, act_class->GetName());
94
95
if
( value && TPython::CPPInstance_Check(value) ) {
96
return
CPPInstance_ASVOIDPTR
(value);
97
}
98
Py_XDECREF(value);
99
throw
CPyCppyy::PyException();
100
return
0;
101
}
102
103
void
*
PyDataBucket::cast
(
const
std::type_info&
tinfo
,
104
IRegisterTransient
*
/*itr*/
,
105
bool
/*isConst*/
)
106
{
107
RootUtils::PyGILStateEnsure
gil;
108
// if regular PyObject, meaningless
109
if
(
m_clid
==
PyCLID
) {
110
return
0;
111
}
112
113
// if requested type is same than myself ==> no conversion needed
114
TClass* tcls = objectIsA (
m_pyObj
);
115
if
( tcls && (
tinfo
== *(tcls->GetTypeInfo())) ) {
116
return
CPPInstance_ASVOIDPTR
(
m_pyObj
);
117
}
118
void
* address =
CPPInstance_ASVOIDPTR
(
m_pyObj
);
119
120
// try SG-based conversion functions
121
{
122
void
* o =
m_bib
?
m_bib
->cast(address,
tinfo
) : 0;
123
if
( o ) {
return
o; }
124
}
125
126
// this will be a conversion for a class instance only (see below:
127
// verified that only a CPPInstance is expected), so bind with cast
128
TClass* clsnew = TClass::GetClass (
tinfo
);
129
if
(!clsnew) {
130
PyErr_SetString
131
( PyExc_RuntimeError,
132
"SG::PyDataBucket::cast() can't find TClass"
);
133
return
0;
134
}
135
TClass* act_class = clsnew->GetActualClass (address);
136
PyObject
* value = TPython::CPPInstance_FromVoidPtr (address, act_class->GetName());
137
PyErr_Clear();
138
139
if
( value && TPython::CPPInstance_Check(value) ) {
140
return
CPPInstance_ASVOIDPTR
(value);
141
}
142
Py_XDECREF(value);
143
//throw PyROOT::TPyException();
144
return
0;
145
}
146
147
void
PyDataBucket::lock
()
148
{
149
RootUtils::PyGILStateEnsure
gil;
150
if
(!
m_pyObj
)
return
;
151
if
(!PyObject_HasAttrString (
m_pyObj
,
"lock"
))
152
return
;
153
PyObject
*
lock
= PyObject_GetAttrString (
m_pyObj
,
"lock"
);
154
if
(!
lock
)
return
;
155
if
(PyCallable_Check (
lock
)) {
156
PyObject
* ret = PyObject_CallObject (
lock
, NULL);
157
Py_DECREF (ret);
158
}
159
Py_DECREF (
lock
);
160
}
161
163
// PyProxyMgr
164
165
PyProxyMgr::PyProxyMgr
()
166
{
167
m_aliases
=
importDictAliases
();
168
m_clids
= PyDict_New();
169
m_clidSvc
= 0;
170
{
171
ServiceHandle<IClassIDSvc>
svc(
"ClassIDSvc"
,
"SgPyDataModel"
);
172
if
( !svc.retrieve().isSuccess()) {
173
throw
std::runtime_error
174
(
"SG::PyProxyMgr: Could not retrieve ClassIDSvc"
);
175
}
176
m_clidSvc
= svc.operator->();
177
}
178
m_dictSvc
= 0;
179
{
180
ServiceHandle<IDictLoaderSvc>
svc(
"AthDictLoaderSvc"
,
"SgPyDataModel"
);
181
if
( !svc.retrieve().isSuccess()) {
182
throw
std::runtime_error
183
(
"SG::PyProxyMgr: Could not retrieve AthDictLoaderSvc"
);
184
}
185
m_dictSvc
= svc.operator->();
186
}
187
}
188
189
PyProxyMgr::~PyProxyMgr
()
190
{
191
// Don't do this if don't have a valid thread state.
192
// (With py3, the interpreter gets shut down before global dtors run...)
193
if
(PyThreadState_GetUnchecked())
194
{
195
Py_DECREF(
m_aliases
);
196
Py_DECREF(
m_clids
);
197
}
198
// delete the proxy dicts...
199
for
( PyProxyMap_t::iterator
200
i =
m_proxyMap
.begin(),
201
iEnd =
m_proxyMap
.end();
202
i != iEnd;
203
++i ) {
204
delete
i->second; i->second = 0;
205
}
206
}
207
208
}
//< end namespace SG
CPPInstance_ASVOIDPTR
#define CPPInstance_ASVOIDPTR(o)
Definition
AthenaPyRoot.h:20
CLID
uint32_t CLID
The Class ID type.
Definition
Event/xAOD/xAODCore/xAODCore/ClassID_traits.h:47
PyObject
_object PyObject
Definition
IPyComponent.h:27
PyCLID
const CLID PyCLID
Definition
SgPyDataModel.cxx:13
SgPyDataModel.h
checker_macros.h
Define macros for attributes used to control the static checker.
ATLAS_NO_CHECK_FILE_THREAD_SAFETY
#define ATLAS_NO_CHECK_FILE_THREAD_SAFETY
Definition
checker_macros.h:209
DataBucketBase::DataBucketBase
DataBucketBase()
Definition
DataBucketBase.h:28
RootUtils::PyGILStateEnsure
Definition
PyAthenaGILStateEnsure.h:20
SG::BaseInfoBase
The non-template portion of the BaseInfo implementation.
Definition
Control/AthenaKernel/AthenaKernel/BaseInfo.h:451
SG::IRegisterTransient
Interface for registering a transient object in t2p map.
Definition
IRegisterTransient.h:28
SG::PyDataBucket::PyDataBucket
PyDataBucket(PyObject *obj, CLID clid)
Constructor.
Definition
SgPyDataModel.cxx:43
SG::PyDataBucket::m_pyObj
PyObject * m_pyObj
Pointer to the held pyroot object (or 'regular' PyObject).
Definition
SgPyDataModel.h:178
SG::PyDataBucket::cast
virtual void * cast(CLID clid, IRegisterTransient *itr=0, bool isConst=true) override
Return the contents of the DataBucket, converted to type given by clid.
Definition
SgPyDataModel.cxx:54
SG::PyDataBucket::lock
virtual void lock() override
If the held object derives from ILockable, call lock() on it.
Definition
SgPyDataModel.cxx:147
SG::PyDataBucket::m_clid
CLID m_clid
The class ID of the wrapped object.
Definition
SgPyDataModel.h:181
SG::PyDataBucket::tinfo
virtual const std::type_info & tinfo() const override
Return the type_info for the stored object.
Definition
SgPyDataModel.h:158
SG::PyDataBucket::m_bib
const SG::BaseInfoBase * m_bib
pointer to the SG::BaseInfoBase structure holding the converter functions for objects held by StoreGa...
Definition
SgPyDataModel.h:185
ServiceHandle
Definition
ClusterMakerTool.h:36
find
std::string find(const std::string &s)
return a remapped string
Definition
hcg.cxx:140
RootUtils::PyGetString
std::pair< std::string, bool > PyGetString(PyObject *s)
Convert python string -> C++ string for py2 and py3.
Definition
PyGetString.h:40
SG
Forward declaration.
Definition
CaloCellPacker_400_500.h:32
SG::PyProxyMgr::importDictAliases
PyObject * importDictAliases()
import the dictionary of aliases from a well known location
Definition
SgPyDataModel.h:369
SG::PyProxyMgr::instance
static PyProxyMgr & instance()
Definition
SgPyDataModel.h:209
SG::PyProxyMgr::m_aliases
PyObject * m_aliases
a dictionary of "typedef'ed typename" -> "typename"
Definition
SgPyDataModel.h:196
SG::PyProxyMgr::PyProxyMgr
PyProxyMgr()
Definition
SgPyDataModel.cxx:165
SG::PyProxyMgr::m_proxyMap
PyProxyMap_t m_proxyMap
Definition
SgPyDataModel.h:202
SG::PyProxyMgr::~PyProxyMgr
~PyProxyMgr()
Definition
SgPyDataModel.cxx:189
SG::PyProxyMgr::m_dictSvc
IDictLoaderSvc * m_dictSvc
Definition
SgPyDataModel.h:193
SG::PyProxyMgr::m_clidSvc
IClassIDSvc * m_clidSvc
Definition
SgPyDataModel.h:194
SG::PyProxyMgr::pytp
PyObject * pytp(PyObject *clid)
returns a borrowed reference
Definition
SgPyDataModel.h:238
SG::PyProxyMgr::m_clids
PyObject * m_clids
a dictionary of 'typename' -> CLID (and reverse CLID->'typename')
Definition
SgPyDataModel.h:199
Generated on
for ATLAS Offline Software by
1.17.0