Logo ROOT  
Reference Guide
PyzCppHelpers.cxx
Go to the documentation of this file.
1// Author: Danilo Piparo CERN 08/2018
2
3/*************************************************************************
4 * Copyright (C) 1995-2018, Rene Brun and Fons Rademakers. *
5 * All rights reserved. *
6 * *
7 * For the licensing terms see $ROOTSYS/LICENSE. *
8 * For the list of contributors see $ROOTSYS/README/CREDITS. *
9 *************************************************************************/
10
11/**
12
13Set of helper functions that are invoked from the C++ implementation of
14pythonizations.
15
16*/
17#include "PyzCppHelpers.hxx"
18
19// Call method with signature: obj->meth()
20PyObject *CallPyObjMethod(PyObject *obj, const char *meth)
21{
22 return PyObject_CallMethod(obj, const_cast<char *>(meth), const_cast<char *>(""));
23}
24
25// Call method with signature: obj->meth(arg1)
26PyObject *CallPyObjMethod(PyObject *obj, const char *meth, PyObject *arg1)
27{
28 return PyObject_CallMethod(obj, const_cast<char *>(meth), const_cast<char *>("O"), arg1);
29}
30
31// Convert generic python object into a boolean value
33{
34 if (PyObject_IsTrue(value) == 1) {
35 Py_DECREF(value);
37 } else {
38 Py_XDECREF(value);
40 }
41}
42
43// Get the TClass of the C++ object proxied by pyobj
45{
47}
48
49////////////////////////////////////////////////////////////////////////////
50/// \brief Convert Numpy data-type string to the according C++ data-type string
51/// \param[in] dtype Numpy data-type string
52/// \return C++ data-type string
53///
54/// If the input data-tyep is not known, the function returns an empty string.
55std::string GetCppTypeFromNumpyType(const std::string& dtype) {
56 if (dtype == "i4") {
57 return "int";
58 } else if (dtype == "u4") {
59 return "unsigned int";
60 } else if (dtype == "i8") {
61 return "Long64_t";
62 } else if (dtype == "u8") {
63 return "ULong64_t";
64 } else if (dtype == "f4") {
65 return "float";
66 } else if (dtype == "f8") {
67 return "double";
68 } else {
69 PyErr_SetString(PyExc_RuntimeError, ("Object not convertible: Python object has unknown data-type '" + dtype + "'.").c_str());
70 return "";
71 }
72}
73
74////////////////////////////////////////////////////////////////////////////
75/// \brief Get Numpy array interface and perform error handling
76/// \param[in] obj PyObject with array interface dictionary
77/// \return Array interface dictionary
79{
80 auto pyinterface = PyObject_GetAttrString(obj, "__array_interface__");
81 if (!pyinterface) {
82 PyErr_SetString(PyExc_RuntimeError, "Object not convertible: __array_interface__ does not exist.");
83 return NULL;
84 }
85 if (!PyDict_Check(pyinterface)) {
86 PyErr_SetString(PyExc_RuntimeError, "Object not convertible: __array_interface__ is not a dictionary.");
87 return NULL;
88 }
89 return pyinterface;
90}
91
92////////////////////////////////////////////////////////////////////////////
93/// \brief Get data pointer from Numpy array interface and perform error handling
94/// \param[in] obj Array interface dictionary
95/// \return Data pointer
97{
98 auto pydata = PyDict_GetItemString(obj, "data");
99 if (!pydata) {
100 PyErr_SetString(PyExc_RuntimeError, "Object not convertible: __array_interface__['data'] does not exist.");
101 return 0;
102 }
103 return PyLong_AsLong(PyTuple_GetItem(pydata, 0));
104}
105
106////////////////////////////////////////////////////////////////////////////
107/// \brief Get type string from Numpy array interface and perform error handling
108/// \param[in] obj Array interface dictionary
109/// \return Type string
111{
112 auto pytypestr = PyDict_GetItemString(obj, "typestr");
113 if (!pytypestr) {
114 PyErr_SetString(PyExc_RuntimeError, "Object not convertible: __array_interface__['typestr'] does not exist.");
115 return "";
116 }
117 std::string typestr = CPyCppyy_PyText_AsString(pytypestr);
118 const auto length = typestr.length();
119 if(length != 3) {
120 PyErr_SetString(PyExc_RuntimeError,
121 ("Object not convertible: __array_interface__['typestr'] returned '" + typestr + "' with invalid length unequal 3.").c_str());
122 return "";
123 }
124 return typestr;
125}
126
127////////////////////////////////////////////////////////////////////////////
128/// \brief Get size of data type in bytes from Numpy type string
129/// \param[in] typestr Numpy type string
130/// \return Size in bytes
131unsigned int GetDatatypeSizeFromTypestr(const std::string& typestr)
132{
133 const auto length = typestr.size();
134 const auto dtypesizestr = typestr.substr(length - 1, length);
135 return std::stoi(dtypesizestr);
136}
137
138////////////////////////////////////////////////////////////////////////////
139/// \brief Check whether endianess in type string matches the endianess of ROOT
140/// \param[in] typestr Numpy type string
141/// \return Boolean indicating whether they match
142bool CheckEndianessFromTypestr(const std::string& typestr)
143{
144 const auto endianess = typestr.substr(1, 2);
145#ifdef R__BYTESWAP
146 const auto byteswap = "<";
147#else
148 const auto byteswap = ">";
149#endif
150 if (!endianess.compare(byteswap)) {
151 PyErr_SetString(PyExc_RuntimeError, "Object not convertible: Endianess of __array_interface__['typestr'] does not match endianess of ROOT.");
152 return false;
153 }
154 return true;
155}
#define Py_RETURN_TRUE
Definition: CPyCppyy.h:285
#define Py_RETURN_FALSE
Definition: CPyCppyy.h:289
#define CPyCppyy_PyText_AsString
Definition: CPyCppyy.h:97
_object PyObject
Definition: PyMethodBase.h:41
PyObject * BoolNot(PyObject *value)
TClass * GetTClass(const CPyCppyy::CPPInstance *pyobj)
unsigned long long GetDataPointerFromArrayInterface(PyObject *obj)
Get data pointer from Numpy array interface and perform error handling.
unsigned int GetDatatypeSizeFromTypestr(const std::string &typestr)
Get size of data type in bytes from Numpy type string.
std::string GetCppTypeFromNumpyType(const std::string &dtype)
Convert Numpy data-type string to the according C++ data-type string.
std::string GetTypestrFromArrayInterface(PyObject *obj)
Get type string from Numpy array interface and perform error handling.
bool CheckEndianessFromTypestr(const std::string &typestr)
Check whether endianess in type string matches the endianess of ROOT.
PyObject * CallPyObjMethod(PyObject *obj, const char *meth)
Set of helper functions that are invoked from the C++ implementation of pythonizations.
PyObject * GetArrayInterface(PyObject *obj)
Get Numpy array interface and perform error handling.
Cppyy::TCppType_t ObjectIsA(bool check_smart=true) const
Definition: CPPInstance.h:106
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition: TClass.h:80
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition: TClass.cxx:2948
RPY_EXPORTED std::string GetScopedFinalName(TCppType_t type)