Logo ROOT  
Reference Guide
RVecPyz.cxx
Go to the documentation of this file.
1// Author: Stefan Wunsch CERN 02/2019
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#include "CPyCppyy.h"
13#include "CPPInstance.h"
14#include "ProxyWrappers.h"
15#include "PyROOTPythonize.h"
16#include "TInterpreter.h"
17#include "PyzCppHelpers.hxx"
18
19#include <sstream>
20
21////////////////////////////////////////////////////////////////////////////
22/// \brief Adopt memory of a Python object with array interface using an RVec
23/// \param[in] self self object
24/// \param[in] obj PyObject with array interface
25///
26/// This function returns an RVec which adopts the memory of the given
27/// PyObject. The RVec takes the data pointer and the size from the array
28/// interface dictionary.
30{
31 if (!obj) {
32 PyErr_SetString(PyExc_RuntimeError, "Object not convertible: Invalid Python object.");
33 return NULL;
34 }
35
36 // Get array interface of object
37 auto pyinterface = GetArrayInterface(obj);
38 if (pyinterface == NULL)
39 return NULL;
40
41 // Get the data-pointer
42 const auto data = GetDataPointerFromArrayInterface(pyinterface);
43 if (data == 0)
44 return NULL;
45
46 // Get the size of the contiguous memory
47 auto pyshape = PyDict_GetItemString(pyinterface, "shape");
48 if (!pyshape) {
49 PyErr_SetString(PyExc_RuntimeError, "Object not convertible: __array_interface__['shape'] does not exist.");
50 return NULL;
51 }
52 long size = 0;
53 for (int i = 0; i < PyTuple_Size(pyshape); i++) {
54 if (size == 0) size = 1;
55 size *= PyLong_AsLong(PyTuple_GetItem(pyshape, i));
56 }
57
58 // Get the typestring and properties thereof
59 const auto typestr = GetTypestrFromArrayInterface(pyinterface);
60 if (typestr.compare("") == 0)
61 return NULL;
62 if (!CheckEndianessFromTypestr(typestr))
63 return NULL;
64
65 const auto dtype = typestr.substr(1, typestr.size());
66 std::string cppdtype = GetCppTypeFromNumpyType(dtype);
67 if (cppdtype.compare("") == 0)
68 return NULL;
69
70 // Construct an RVec of the correct data-type
71 const std::string klassname = "ROOT::VecOps::RVec<" + cppdtype + ">";
72 std::stringstream prefix;
73#ifdef _MSC_VER
74 prefix << "0x";
75#endif
76 auto address = (void*) gInterpreter->Calc("new " + klassname + "(reinterpret_cast<" + cppdtype + "*>(" + prefix.str() + data + ")," + size + ")");
77
78 // Bind the object to a Python-side proxy
79 auto klass = (Cppyy::TCppType_t)Cppyy::GetScope(klassname);
80 auto pyobj = CPyCppyy::BindCppObject(address, klass);
81
82 // Give Python the ownership of the underlying C++ object
83 ((CPyCppyy::CPPInstance*)pyobj)->PythonOwns();
84
85 // Bind pyobject holding adopted memory to the RVec
86 if (PyObject_SetAttrString(pyobj, "__adopted__", obj)) {
87 PyErr_SetString(PyExc_RuntimeError, "Object not convertible: Failed to set Python object as attribute __adopted__.");
88 return NULL;
89 }
90
91 // Clean-up and return
92 Py_DECREF(pyinterface);
93 return pyobj;
94}
_object PyObject
Definition: PyMethodBase.h:43
unsigned long long GetDataPointerFromArrayInterface(PyObject *obj)
Get data pointer from Numpy array interface and perform error handling.
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 * GetArrayInterface(PyObject *obj)
Get Numpy array interface and perform error handling.
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
#define gInterpreter
Definition: TInterpreter.h:564
PyObject * BindCppObject(Cppyy::TCppObject_t object, Cppyy::TCppType_t klass, const unsigned flags=0)
TCppScope_t TCppType_t
Definition: cpp_cppyy.h:19
RPY_EXPORTED TCppScope_t GetScope(const std::string &scope_name)
PyObject * AsRVec(PyObject *self, PyObject *obj)
Adopt memory of a Python object with array interface using an RVec.
Definition: RVecPyz.cxx:29