Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TClassPyz.cxx
Go to the documentation of this file.
1// Author: Enric Tejedor CERN 02/2019
2// Original PyROOT code by Wim Lavrijsen, LBL
3
4/*************************************************************************
5 * Copyright (C) 1995-2019, 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 "PyROOTPythonize.h"
15#include "PyROOTStrings.h"
16#include "CPPInstance.h"
17#include "Utility.h"
18#include "ProxyWrappers.h"
19#include "PyzCppHelpers.hxx"
20
21// ROOT
22#include "TClass.h"
23
24using namespace CPyCppyy;
25
26// Cast the void* returned by TClass::DynamicCast to the right type
28{
29 // Parse arguments
30 CPPInstance *pyclass = nullptr;
31 PyObject *pyobject = nullptr;
32 int up = 1;
33 if (!PyArg_ParseTuple(args, const_cast<char *>("O!O|i:DynamicCast"),
34 &CPPInstance_Type, &pyclass,
35 &pyobject,
36 &up))
37 return nullptr;
38
39 // Perform actual cast - calls default implementation of DynamicCast
40 auto meth = PyObject_GetAttr((PyObject *)self, PyROOT::PyStrings::gTClassDynCast);
41 auto ptr = meth ? PyObject_Call(meth, args, nullptr) : nullptr;
42 Py_XDECREF(meth);
43
44 // Simply forward in case of call failure
45 if (!ptr)
46 return nullptr;
47
48 // Retrieve object address
49 void *address = nullptr;
50 if (CPPInstance_Check(pyobject)) {
51 address = ((CPPInstance *)pyobject)->GetObject();
52 } else if (PyInt_Check(pyobject) || PyLong_Check(pyobject)) {
53 address = (void *)PyLong_AsLong(pyobject);
54 } else {
55 Utility::GetBuffer(pyobject, '*', 1, address, false);
56 }
57
58 if (PyErr_Occurred()) {
59 // Error getting object address, just return the void* wrapper
60 PyErr_Clear();
61 return ptr;
62 }
63
64 // Now use binding to return a usable class
65 TClass *klass = nullptr;
66 if (up) {
67 // Upcast: result is a base
68 klass = (TClass *)GetTClass(pyclass)->DynamicCast(TClass::Class(), pyclass->GetObject());
69 } else {
70 // Downcast: result is a derived
71 klass = (TClass *)GetTClass(self)->DynamicCast(TClass::Class(), self->GetObject());
72 }
73
74 PyObject *result = BindCppObjectNoCast(address, Cppyy::GetScope(klass->GetName()));
75 Py_DECREF(ptr);
76
77 return result;
78}
79
80////////////////////////////////////////////////////////////////////////////
81/// \brief Add pythonization for TClass::DynamicCast.
82/// \param[in] self Always null, since this is a module function.
83/// \param[in] args Pointer to a Python tuple object containing the arguments
84/// received from Python.
85///
86/// TClass::DynamicCast returns a void* that the user still has to cast (it
87/// will have the proper offset, though). Fix this by providing the requested
88/// binding if the cast succeeded.
90{
91 PyObject *pyclass = PyTuple_GetItem(args, 0);
92 Utility::AddToClass(pyclass, "_TClass__DynamicCast", "DynamicCast");
93 Utility::AddToClass(pyclass, "DynamicCast", (PyCFunction)TClassDynamicCastPyz);
95}
#define Py_RETURN_NONE
Definition CPyCppyy.h:289
_object PyObject
TClass * GetTClass(const CPyCppyy::CPPInstance *pyobj)
PyObject * TClassDynamicCastPyz(CPPInstance *self, PyObject *args)
Definition TClassPyz.cxx:27
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:80
void * DynamicCast(const TClass *base, void *obj, Bool_t up=kTRUE)
Cast obj of this class type up to baseclass cl if up is true.
Definition TClass.cxx:4901
virtual const char * GetName() const
Returns name of object.
Definition TNamed.h:47
Py_ssize_t GetBuffer(PyObject *pyobject, char tc, int size, void *&buf, bool check=true)
Definition Utility.cxx:614
bool AddToClass(PyObject *pyclass, const char *label, PyCFunction cfunc, int flags=METH_VARARGS)
Definition Utility.cxx:169
Set of helper functions that are invoked from the pythonizors, on the Python side.
PyTypeObject CPPInstance_Type
PyObject * BindCppObjectNoCast(Cppyy::TCppObject_t object, Cppyy::TCppType_t klass, const unsigned flags=0)
bool CPPInstance_Check(T *object)
RPY_EXPORTED TCppScope_t GetScope(const std::string &scope_name)
R__EXTERN PyObject * gTClassDynCast
PyObject * AddTClassDynamicCastPyz(PyObject *self, PyObject *args)
Add pythonization for TClass::DynamicCast.
Definition TClassPyz.cxx:89