1edb35d95SEugene Zelenko //===-- PythonDataObjects.h--------------------------------------*- C++ -*-===// 22c1f46dcSZachary Turner // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 62c1f46dcSZachary Turner // 72c1f46dcSZachary Turner //===----------------------------------------------------------------------===// 82c1f46dcSZachary Turner 9085328eeSLawrence D'Anna // 10085328eeSLawrence D'Anna // !! FIXME FIXME FIXME !! 11085328eeSLawrence D'Anna // 12085328eeSLawrence D'Anna // Python APIs nearly all can return an exception. They do this 13085328eeSLawrence D'Anna // by returning NULL, or -1, or some such value and setting 14085328eeSLawrence D'Anna // the exception state with PyErr_Set*(). Exceptions must be 15085328eeSLawrence D'Anna // handled before further python API functions are called. Failure 16085328eeSLawrence D'Anna // to do so will result in asserts on debug builds of python. 17085328eeSLawrence D'Anna // It will also sometimes, but not usually result in crashes of 18085328eeSLawrence D'Anna // release builds. 19085328eeSLawrence D'Anna // 20085328eeSLawrence D'Anna // Nearly all the code in this header does not handle python exceptions 21085328eeSLawrence D'Anna // correctly. It should all be converted to return Expected<> or 22085328eeSLawrence D'Anna // Error types to capture the exception. 23085328eeSLawrence D'Anna // 24085328eeSLawrence D'Anna // Everything in this file except functions that return Error or 25085328eeSLawrence D'Anna // Expected<> is considered deprecated and should not be 26085328eeSLawrence D'Anna // used in new code. If you need to use it, fix it first. 27085328eeSLawrence D'Anna // 28d3bd5b3dSLawrence D'Anna // 29d3bd5b3dSLawrence D'Anna // TODOs for this file 30d3bd5b3dSLawrence D'Anna // 31d3bd5b3dSLawrence D'Anna // * Make all methods safe for exceptions. 32d3bd5b3dSLawrence D'Anna // 33d3bd5b3dSLawrence D'Anna // * Eliminate method signatures that must translate exceptions into 34d3bd5b3dSLawrence D'Anna // empty objects or NULLs. Almost everything here should return 35d3bd5b3dSLawrence D'Anna // Expected<>. It should be acceptable for certain operations that 36d3bd5b3dSLawrence D'Anna // can never fail to assert instead, such as the creation of 37d3bd5b3dSLawrence D'Anna // PythonString from a string literal. 38d3bd5b3dSLawrence D'Anna // 39d3bd5b3dSLawrence D'Anna // * Elimintate Reset(), and make all non-default constructors private. 40d3bd5b3dSLawrence D'Anna // Python objects should be created with Retain<> or Take<>, and they 41d3bd5b3dSLawrence D'Anna // should be assigned with operator= 42d3bd5b3dSLawrence D'Anna // 43d3bd5b3dSLawrence D'Anna // * Eliminate default constructors, make python objects always 44d3bd5b3dSLawrence D'Anna // nonnull, and use optionals where necessary. 45d3bd5b3dSLawrence D'Anna // 46d3bd5b3dSLawrence D'Anna 47085328eeSLawrence D'Anna 482c1f46dcSZachary Turner #ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H 492c1f46dcSZachary Turner #define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H 502c1f46dcSZachary Turner 51d68983e3SPavel Labath #ifndef LLDB_DISABLE_PYTHON 52d68983e3SPavel Labath 5341de9a97SKate Stone // LLDB Python header must be included first 5441de9a97SKate Stone #include "lldb-python.h" 5541de9a97SKate Stone 569c40264fSZachary Turner #include "lldb/Host/File.h" 57f2a8bccfSPavel Labath #include "lldb/Utility/StructuredData.h" 582c1f46dcSZachary Turner 595a72c02bSZachary Turner #include "llvm/ADT/ArrayRef.h" 605a72c02bSZachary Turner 612c1f46dcSZachary Turner namespace lldb_private { 62*04edd189SLawrence D'Anna namespace python { 63edb35d95SEugene Zelenko 64085328eeSLawrence D'Anna class PythonObject; 655a72c02bSZachary Turner class PythonBytes; 662c1f46dcSZachary Turner class PythonString; 672c1f46dcSZachary Turner class PythonList; 682c1f46dcSZachary Turner class PythonDictionary; 692c1f46dcSZachary Turner class PythonInteger; 70085328eeSLawrence D'Anna class PythonException; 712c1f46dcSZachary Turner 72b9c1b51eSKate Stone class StructuredPythonObject : public StructuredData::Generic { 732c1f46dcSZachary Turner public: 74b9c1b51eSKate Stone StructuredPythonObject() : StructuredData::Generic() {} 752c1f46dcSZachary Turner 76b9c1b51eSKate Stone StructuredPythonObject(void *obj) : StructuredData::Generic(obj) { 772c1f46dcSZachary Turner Py_XINCREF(GetValue()); 782c1f46dcSZachary Turner } 792c1f46dcSZachary Turner 80b9c1b51eSKate Stone ~StructuredPythonObject() override { 812c1f46dcSZachary Turner if (Py_IsInitialized()) 822c1f46dcSZachary Turner Py_XDECREF(GetValue()); 832c1f46dcSZachary Turner SetValue(nullptr); 842c1f46dcSZachary Turner } 852c1f46dcSZachary Turner 86b9c1b51eSKate Stone bool IsValid() const override { return GetValue() && GetValue() != Py_None; } 872c1f46dcSZachary Turner 882783d817SJonas Devlieghere void Serialize(llvm::json::OStream &s) const override; 892c1f46dcSZachary Turner 902c1f46dcSZachary Turner private: 912c1f46dcSZachary Turner DISALLOW_COPY_AND_ASSIGN(StructuredPythonObject); 922c1f46dcSZachary Turner }; 932c1f46dcSZachary Turner 94b9c1b51eSKate Stone enum class PyObjectType { 952c1f46dcSZachary Turner Unknown, 962c1f46dcSZachary Turner None, 97b81d715cSTatyana Krasnukha Boolean, 982c1f46dcSZachary Turner Integer, 992c1f46dcSZachary Turner Dictionary, 1002c1f46dcSZachary Turner List, 1019c40264fSZachary Turner String, 1025a72c02bSZachary Turner Bytes, 103f9d6d204SZachary Turner ByteArray, 1047841efbbSZachary Turner Module, 105a1405147SZachary Turner Callable, 106a1405147SZachary Turner Tuple, 1079c40264fSZachary Turner File 1082c1f46dcSZachary Turner }; 1092c1f46dcSZachary Turner 110b9c1b51eSKate Stone enum class PyRefType { 111f8b22f8fSZachary Turner Borrowed, // We are not given ownership of the incoming PyObject. 112f8b22f8fSZachary Turner // We cannot safely hold it without calling Py_INCREF. 113f8b22f8fSZachary Turner Owned // We have ownership of the incoming PyObject. We should 114f8b22f8fSZachary Turner // not call Py_INCREF. 115f8b22f8fSZachary Turner }; 116f8b22f8fSZachary Turner 117085328eeSLawrence D'Anna 118085328eeSLawrence D'Anna // Take a reference that you already own, and turn it into 119085328eeSLawrence D'Anna // a PythonObject. 120085328eeSLawrence D'Anna // 121085328eeSLawrence D'Anna // Most python API methods will return a +1 reference 122085328eeSLawrence D'Anna // if they succeed or NULL if and only if 123085328eeSLawrence D'Anna // they set an exception. Use this to collect such return 124085328eeSLawrence D'Anna // values, after checking for NULL. 125085328eeSLawrence D'Anna // 126085328eeSLawrence D'Anna // If T is not just PythonObject, then obj must be already be 127085328eeSLawrence D'Anna // checked to be of the correct type. 128085328eeSLawrence D'Anna template <typename T> T Take(PyObject *obj) { 129085328eeSLawrence D'Anna assert(obj); 130085328eeSLawrence D'Anna assert(!PyErr_Occurred()); 131085328eeSLawrence D'Anna T thing(PyRefType::Owned, obj); 132085328eeSLawrence D'Anna assert(thing.IsValid()); 133085328eeSLawrence D'Anna return std::move(thing); 134085328eeSLawrence D'Anna } 135085328eeSLawrence D'Anna 136085328eeSLawrence D'Anna // Retain a reference you have borrowed, and turn it into 137085328eeSLawrence D'Anna // a PythonObject. 138085328eeSLawrence D'Anna // 139085328eeSLawrence D'Anna // A minority of python APIs return a borrowed reference 140085328eeSLawrence D'Anna // instead of a +1. They will also return NULL if and only 141085328eeSLawrence D'Anna // if they set an exception. Use this to collect such return 142085328eeSLawrence D'Anna // values, after checking for NULL. 143085328eeSLawrence D'Anna // 144085328eeSLawrence D'Anna // If T is not just PythonObject, then obj must be already be 145085328eeSLawrence D'Anna // checked to be of the correct type. 146085328eeSLawrence D'Anna template <typename T> T Retain(PyObject *obj) { 147085328eeSLawrence D'Anna assert(obj); 148085328eeSLawrence D'Anna assert(!PyErr_Occurred()); 149085328eeSLawrence D'Anna T thing(PyRefType::Borrowed, obj); 150085328eeSLawrence D'Anna assert(thing.IsValid()); 151085328eeSLawrence D'Anna return std::move(thing); 152085328eeSLawrence D'Anna } 153085328eeSLawrence D'Anna 154722b6189SLawrence D'Anna // This class can be used like a utility function to convert from 155722b6189SLawrence D'Anna // a llvm-friendly Twine into a null-terminated const char *, 156722b6189SLawrence D'Anna // which is the form python C APIs want their strings in. 157722b6189SLawrence D'Anna // 158722b6189SLawrence D'Anna // Example: 159722b6189SLawrence D'Anna // const llvm::Twine &some_twine; 160722b6189SLawrence D'Anna // PyFoo_Bar(x, y, z, NullTerminated(some_twine)); 161722b6189SLawrence D'Anna // 162722b6189SLawrence D'Anna // Why a class instead of a function? If the twine isn't already null 163722b6189SLawrence D'Anna // terminated, it will need a temporary buffer to copy the string 164722b6189SLawrence D'Anna // into. We need that buffer to stick around for the lifetime of the 165722b6189SLawrence D'Anna // statement. 166722b6189SLawrence D'Anna class NullTerminated { 167722b6189SLawrence D'Anna const char *str; 168722b6189SLawrence D'Anna llvm::SmallString<32> storage; 169722b6189SLawrence D'Anna 170722b6189SLawrence D'Anna public: 171722b6189SLawrence D'Anna NullTerminated(const llvm::Twine &twine) { 172722b6189SLawrence D'Anna llvm::StringRef ref = twine.toNullTerminatedStringRef(storage); 173722b6189SLawrence D'Anna str = ref.begin(); 174722b6189SLawrence D'Anna } 175722b6189SLawrence D'Anna operator const char *() { return str; } 176722b6189SLawrence D'Anna }; 177722b6189SLawrence D'Anna 178*04edd189SLawrence D'Anna inline llvm::Error nullDeref() { 179*04edd189SLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(), 180*04edd189SLawrence D'Anna "A NULL PyObject* was dereferenced"); 181*04edd189SLawrence D'Anna } 182*04edd189SLawrence D'Anna 183*04edd189SLawrence D'Anna inline llvm::Error exception(const char *s = nullptr) { 184*04edd189SLawrence D'Anna return llvm::make_error<PythonException>(s); 185*04edd189SLawrence D'Anna } 186*04edd189SLawrence D'Anna 187*04edd189SLawrence D'Anna inline llvm::Error keyError() { 188*04edd189SLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(), 189*04edd189SLawrence D'Anna "key not in dict"); 190*04edd189SLawrence D'Anna } 191085328eeSLawrence D'Anna 192b9c1b51eSKate Stone enum class PyInitialValue { Invalid, Empty }; 193f8b22f8fSZachary Turner 194085328eeSLawrence D'Anna template <typename T, typename Enable = void> struct PythonFormat; 195085328eeSLawrence D'Anna 196085328eeSLawrence D'Anna template <> struct PythonFormat<unsigned long long> { 197085328eeSLawrence D'Anna static constexpr char format = 'K'; 198085328eeSLawrence D'Anna static auto get(unsigned long long value) { return value; } 199085328eeSLawrence D'Anna }; 200085328eeSLawrence D'Anna 201085328eeSLawrence D'Anna template <> struct PythonFormat<long long> { 202085328eeSLawrence D'Anna static constexpr char format = 'L'; 203085328eeSLawrence D'Anna static auto get(long long value) { return value; } 204085328eeSLawrence D'Anna }; 205085328eeSLawrence D'Anna 206*04edd189SLawrence D'Anna template <> struct PythonFormat<PyObject *> { 207*04edd189SLawrence D'Anna static constexpr char format = 'O'; 208*04edd189SLawrence D'Anna static auto get(PyObject *value) { return value; } 209*04edd189SLawrence D'Anna }; 210*04edd189SLawrence D'Anna 211085328eeSLawrence D'Anna template <typename T> 212085328eeSLawrence D'Anna struct PythonFormat< 213085328eeSLawrence D'Anna T, typename std::enable_if<std::is_base_of<PythonObject, T>::value>::type> { 214085328eeSLawrence D'Anna static constexpr char format = 'O'; 215085328eeSLawrence D'Anna static auto get(const T &value) { return value.get(); } 216085328eeSLawrence D'Anna }; 217085328eeSLawrence D'Anna 218b9c1b51eSKate Stone class PythonObject { 2192c1f46dcSZachary Turner public: 220b9c1b51eSKate Stone PythonObject() : m_py_obj(nullptr) {} 2212c1f46dcSZachary Turner 222*04edd189SLawrence D'Anna PythonObject(PyRefType type, PyObject *py_obj) { 223*04edd189SLawrence D'Anna m_py_obj = py_obj; 224*04edd189SLawrence D'Anna // If this is a borrowed reference, we need to convert it to 225*04edd189SLawrence D'Anna // an owned reference by incrementing it. If it is an owned 226*04edd189SLawrence D'Anna // reference (for example the caller allocated it with PyDict_New() 227*04edd189SLawrence D'Anna // then we must *not* increment it. 228*04edd189SLawrence D'Anna if (m_py_obj && Py_IsInitialized() && type == PyRefType::Borrowed) 229*04edd189SLawrence D'Anna Py_XINCREF(m_py_obj); 2302c1f46dcSZachary Turner } 2312c1f46dcSZachary Turner 23203819d1cSLawrence D'Anna PythonObject(const PythonObject &rhs) 23303819d1cSLawrence D'Anna : PythonObject(PyRefType::Borrowed, rhs.m_py_obj) {} 2342c1f46dcSZachary Turner 235085328eeSLawrence D'Anna PythonObject(PythonObject &&rhs) { 236085328eeSLawrence D'Anna m_py_obj = rhs.m_py_obj; 237085328eeSLawrence D'Anna rhs.m_py_obj = nullptr; 238085328eeSLawrence D'Anna } 239085328eeSLawrence D'Anna 240d3bd5b3dSLawrence D'Anna ~PythonObject() { Reset(); } 2412c1f46dcSZachary Turner 242b9c1b51eSKate Stone void Reset() { 243085328eeSLawrence D'Anna if (m_py_obj && Py_IsInitialized()) 244085328eeSLawrence D'Anna Py_DECREF(m_py_obj); 245f8b22f8fSZachary Turner m_py_obj = nullptr; 2462c1f46dcSZachary Turner } 247f8b22f8fSZachary Turner 248b9c1b51eSKate Stone void Dump() const { 2492c1f46dcSZachary Turner if (m_py_obj) 2502c1f46dcSZachary Turner _PyObject_Dump(m_py_obj); 2512c1f46dcSZachary Turner else 2522c1f46dcSZachary Turner puts("NULL"); 2532c1f46dcSZachary Turner } 2542c1f46dcSZachary Turner 255b9c1b51eSKate Stone void Dump(Stream &strm) const; 2562c1f46dcSZachary Turner 257b9c1b51eSKate Stone PyObject *get() const { return m_py_obj; } 2582c1f46dcSZachary Turner 259b9c1b51eSKate Stone PyObject *release() { 26060c24f70SZachary Turner PyObject *result = m_py_obj; 26160c24f70SZachary Turner m_py_obj = nullptr; 26260c24f70SZachary Turner return result; 26360c24f70SZachary Turner } 26460c24f70SZachary Turner 26503819d1cSLawrence D'Anna PythonObject &operator=(PythonObject other) { 266085328eeSLawrence D'Anna Reset(); 26703819d1cSLawrence D'Anna m_py_obj = std::exchange(other.m_py_obj, nullptr); 268085328eeSLawrence D'Anna return *this; 269085328eeSLawrence D'Anna } 270085328eeSLawrence D'Anna 271b9c1b51eSKate Stone PyObjectType GetObjectType() const; 2727841efbbSZachary Turner 273b9c1b51eSKate Stone PythonString Repr() const; 2747841efbbSZachary Turner 275b9c1b51eSKate Stone PythonString Str() const; 2767841efbbSZachary Turner 277b9c1b51eSKate Stone static PythonObject ResolveNameWithDictionary(llvm::StringRef name, 278b9c1b51eSKate Stone const PythonDictionary &dict); 2797841efbbSZachary Turner 280b58fb2f4SZachary Turner template <typename T> 281b9c1b51eSKate Stone static T ResolveNameWithDictionary(llvm::StringRef name, 282b9c1b51eSKate Stone const PythonDictionary &dict) { 283b58fb2f4SZachary Turner return ResolveNameWithDictionary(name, dict).AsType<T>(); 284b58fb2f4SZachary Turner } 285b58fb2f4SZachary Turner 286b9c1b51eSKate Stone PythonObject ResolveName(llvm::StringRef name) const; 2877841efbbSZachary Turner 288b9c1b51eSKate Stone template <typename T> T ResolveName(llvm::StringRef name) const { 289b58fb2f4SZachary Turner return ResolveName(name).AsType<T>(); 290b58fb2f4SZachary Turner } 291b58fb2f4SZachary Turner 292b9c1b51eSKate Stone bool HasAttribute(llvm::StringRef attribute) const; 2939c40264fSZachary Turner 294b9c1b51eSKate Stone PythonObject GetAttributeValue(llvm::StringRef attribute) const; 2957d6d218eSZachary Turner 296085328eeSLawrence D'Anna bool IsNone() const { return m_py_obj == Py_None; } 297f8b22f8fSZachary Turner 298085328eeSLawrence D'Anna bool IsValid() const { return m_py_obj != nullptr; } 299f8b22f8fSZachary Turner 300085328eeSLawrence D'Anna bool IsAllocated() const { return IsValid() && !IsNone(); } 301085328eeSLawrence D'Anna 302085328eeSLawrence D'Anna explicit operator bool() const { return IsValid() && !IsNone(); } 3032c1f46dcSZachary Turner 304b9c1b51eSKate Stone template <typename T> T AsType() const { 3057d6d218eSZachary Turner if (!T::Check(m_py_obj)) 3067d6d218eSZachary Turner return T(); 3077d6d218eSZachary Turner return T(PyRefType::Borrowed, m_py_obj); 3087d6d218eSZachary Turner } 3097d6d218eSZachary Turner 310b9c1b51eSKate Stone StructuredData::ObjectSP CreateStructuredObject() const; 3112c1f46dcSZachary Turner 3122c1f46dcSZachary Turner protected: 313c86a6acaSLawrence D'Anna 314c86a6acaSLawrence D'Anna #if PY_MAJOR_VERSION < 3 315c86a6acaSLawrence D'Anna // The python 2 API declares some arguments as char* that should 316c86a6acaSLawrence D'Anna // be const char *, but it doesn't actually modify them. 317c86a6acaSLawrence D'Anna static char *py2_const_cast(const char *s) { return const_cast<char *>(s); } 318c86a6acaSLawrence D'Anna #else 319c86a6acaSLawrence D'Anna static const char *py2_const_cast(const char *s) { return s; } 320c86a6acaSLawrence D'Anna #endif 321085328eeSLawrence D'Anna 322085328eeSLawrence D'Anna public: 323085328eeSLawrence D'Anna template <typename... T> 324085328eeSLawrence D'Anna llvm::Expected<PythonObject> CallMethod(const char *name, 325085328eeSLawrence D'Anna const T &... t) const { 326085328eeSLawrence D'Anna const char format[] = {'(', PythonFormat<T>::format..., ')', 0}; 327085328eeSLawrence D'Anna PyObject *obj = 328c86a6acaSLawrence D'Anna PyObject_CallMethod(m_py_obj, py2_const_cast(name), 329c86a6acaSLawrence D'Anna py2_const_cast(format), PythonFormat<T>::get(t)...); 330c86a6acaSLawrence D'Anna if (!obj) 331c86a6acaSLawrence D'Anna return exception(); 332c86a6acaSLawrence D'Anna return python::Take<PythonObject>(obj); 333c86a6acaSLawrence D'Anna } 334c86a6acaSLawrence D'Anna 335c86a6acaSLawrence D'Anna template <typename... T> 336c86a6acaSLawrence D'Anna llvm::Expected<PythonObject> Call(const T &... t) const { 337c86a6acaSLawrence D'Anna const char format[] = {'(', PythonFormat<T>::format..., ')', 0}; 338c86a6acaSLawrence D'Anna PyObject *obj = PyObject_CallFunction(m_py_obj, py2_const_cast(format), 339c86a6acaSLawrence D'Anna PythonFormat<T>::get(t)...); 340085328eeSLawrence D'Anna if (!obj) 341085328eeSLawrence D'Anna return exception(); 342085328eeSLawrence D'Anna return python::Take<PythonObject>(obj); 343085328eeSLawrence D'Anna } 344085328eeSLawrence D'Anna 345722b6189SLawrence D'Anna llvm::Expected<PythonObject> GetAttribute(const llvm::Twine &name) const { 346085328eeSLawrence D'Anna if (!m_py_obj) 347085328eeSLawrence D'Anna return nullDeref(); 348722b6189SLawrence D'Anna PyObject *obj = PyObject_GetAttrString(m_py_obj, NullTerminated(name)); 349085328eeSLawrence D'Anna if (!obj) 350085328eeSLawrence D'Anna return exception(); 351085328eeSLawrence D'Anna return python::Take<PythonObject>(obj); 352085328eeSLawrence D'Anna } 353085328eeSLawrence D'Anna 354085328eeSLawrence D'Anna llvm::Expected<bool> IsTrue() { 355085328eeSLawrence D'Anna if (!m_py_obj) 356085328eeSLawrence D'Anna return nullDeref(); 357085328eeSLawrence D'Anna int r = PyObject_IsTrue(m_py_obj); 358085328eeSLawrence D'Anna if (r < 0) 359085328eeSLawrence D'Anna return exception(); 360085328eeSLawrence D'Anna return !!r; 361085328eeSLawrence D'Anna } 362085328eeSLawrence D'Anna 363085328eeSLawrence D'Anna llvm::Expected<long long> AsLongLong() { 364085328eeSLawrence D'Anna if (!m_py_obj) 365085328eeSLawrence D'Anna return nullDeref(); 366085328eeSLawrence D'Anna assert(!PyErr_Occurred()); 367085328eeSLawrence D'Anna long long r = PyLong_AsLongLong(m_py_obj); 368085328eeSLawrence D'Anna if (PyErr_Occurred()) 369085328eeSLawrence D'Anna return exception(); 370085328eeSLawrence D'Anna return r; 371085328eeSLawrence D'Anna } 372085328eeSLawrence D'Anna 373085328eeSLawrence D'Anna llvm::Expected<bool> IsInstance(const PythonObject &cls) { 374085328eeSLawrence D'Anna if (!m_py_obj || !cls.IsValid()) 375085328eeSLawrence D'Anna return nullDeref(); 376085328eeSLawrence D'Anna int r = PyObject_IsInstance(m_py_obj, cls.get()); 377085328eeSLawrence D'Anna if (r < 0) 378085328eeSLawrence D'Anna return exception(); 379085328eeSLawrence D'Anna return !!r; 380085328eeSLawrence D'Anna } 381085328eeSLawrence D'Anna 382085328eeSLawrence D'Anna protected: 3832c1f46dcSZachary Turner PyObject *m_py_obj; 3842c1f46dcSZachary Turner }; 3852c1f46dcSZachary Turner 386085328eeSLawrence D'Anna 387085328eeSLawrence D'Anna // This is why C++ needs monads. 388085328eeSLawrence D'Anna template <typename T> llvm::Expected<T> As(llvm::Expected<PythonObject> &&obj) { 389085328eeSLawrence D'Anna if (!obj) 390085328eeSLawrence D'Anna return obj.takeError(); 391085328eeSLawrence D'Anna if (!T::Check(obj.get().get())) 392085328eeSLawrence D'Anna return llvm::createStringError(llvm::inconvertibleErrorCode(), 393085328eeSLawrence D'Anna "type error"); 394085328eeSLawrence D'Anna return T(PyRefType::Borrowed, std::move(obj.get().get())); 395085328eeSLawrence D'Anna } 396085328eeSLawrence D'Anna 397085328eeSLawrence D'Anna template <> llvm::Expected<bool> As<bool>(llvm::Expected<PythonObject> &&obj); 398085328eeSLawrence D'Anna 399085328eeSLawrence D'Anna template <> 400085328eeSLawrence D'Anna llvm::Expected<long long> As<long long>(llvm::Expected<PythonObject> &&obj); 401085328eeSLawrence D'Anna 402c86a6acaSLawrence D'Anna template <> 403c86a6acaSLawrence D'Anna llvm::Expected<std::string> As<std::string>(llvm::Expected<PythonObject> &&obj); 404c86a6acaSLawrence D'Anna 405085328eeSLawrence D'Anna 406d3bd5b3dSLawrence D'Anna template <class T> class TypedPythonObject : public PythonObject { 4075a72c02bSZachary Turner public: 408d3bd5b3dSLawrence D'Anna // override to perform implicit type conversions on Reset 409d3bd5b3dSLawrence D'Anna // This can be eliminated once we drop python 2 support. 410d3bd5b3dSLawrence D'Anna static void Convert(PyRefType &type, PyObject *&py_obj) {} 411d3bd5b3dSLawrence D'Anna 412722b6189SLawrence D'Anna TypedPythonObject(PyRefType type, PyObject *py_obj) { 413d3bd5b3dSLawrence D'Anna if (!py_obj) 414d3bd5b3dSLawrence D'Anna return; 415d3bd5b3dSLawrence D'Anna T::Convert(type, py_obj); 416d3bd5b3dSLawrence D'Anna if (T::Check(py_obj)) 417*04edd189SLawrence D'Anna PythonObject::operator=(PythonObject(type, py_obj)); 418d3bd5b3dSLawrence D'Anna else if (type == PyRefType::Owned) 419d3bd5b3dSLawrence D'Anna Py_DECREF(py_obj); 420d3bd5b3dSLawrence D'Anna } 421d3bd5b3dSLawrence D'Anna 422d3bd5b3dSLawrence D'Anna TypedPythonObject() {} 423d3bd5b3dSLawrence D'Anna }; 424d3bd5b3dSLawrence D'Anna 425d3bd5b3dSLawrence D'Anna class PythonBytes : public TypedPythonObject<PythonBytes> { 426d3bd5b3dSLawrence D'Anna public: 427d3bd5b3dSLawrence D'Anna using TypedPythonObject::TypedPythonObject; 4285a72c02bSZachary Turner explicit PythonBytes(llvm::ArrayRef<uint8_t> bytes); 4295a72c02bSZachary Turner PythonBytes(const uint8_t *bytes, size_t length); 4305a72c02bSZachary Turner 431b9c1b51eSKate Stone static bool Check(PyObject *py_obj); 4325a72c02bSZachary Turner 433b9c1b51eSKate Stone llvm::ArrayRef<uint8_t> GetBytes() const; 4345a72c02bSZachary Turner 435b9c1b51eSKate Stone size_t GetSize() const; 4365a72c02bSZachary Turner 437b9c1b51eSKate Stone void SetBytes(llvm::ArrayRef<uint8_t> stringbytes); 4385a72c02bSZachary Turner 439b9c1b51eSKate Stone StructuredData::StringSP CreateStructuredString() const; 4405a72c02bSZachary Turner }; 4415a72c02bSZachary Turner 442d3bd5b3dSLawrence D'Anna class PythonByteArray : public TypedPythonObject<PythonByteArray> { 443f9d6d204SZachary Turner public: 444d3bd5b3dSLawrence D'Anna using TypedPythonObject::TypedPythonObject; 445f9d6d204SZachary Turner explicit PythonByteArray(llvm::ArrayRef<uint8_t> bytes); 446f9d6d204SZachary Turner PythonByteArray(const uint8_t *bytes, size_t length); 447f9d6d204SZachary Turner PythonByteArray(const PythonBytes &object); 448f9d6d204SZachary Turner 449b9c1b51eSKate Stone static bool Check(PyObject *py_obj); 450f9d6d204SZachary Turner 451b9c1b51eSKate Stone llvm::ArrayRef<uint8_t> GetBytes() const; 452f9d6d204SZachary Turner 453b9c1b51eSKate Stone size_t GetSize() const; 454f9d6d204SZachary Turner 455b9c1b51eSKate Stone void SetBytes(llvm::ArrayRef<uint8_t> stringbytes); 456f9d6d204SZachary Turner 457b9c1b51eSKate Stone StructuredData::StringSP CreateStructuredString() const; 458f9d6d204SZachary Turner }; 459f9d6d204SZachary Turner 460d3bd5b3dSLawrence D'Anna class PythonString : public TypedPythonObject<PythonString> { 4612c1f46dcSZachary Turner public: 462d3bd5b3dSLawrence D'Anna using TypedPythonObject::TypedPythonObject; 463085328eeSLawrence D'Anna static llvm::Expected<PythonString> FromUTF8(llvm::StringRef string); 464085328eeSLawrence D'Anna 465d3bd5b3dSLawrence D'Anna PythonString() : TypedPythonObject() {} // MSVC requires this for some reason 466edb35d95SEugene Zelenko 467d3bd5b3dSLawrence D'Anna explicit PythonString(llvm::StringRef string); // safe, null on error 4682c1f46dcSZachary Turner 46922c8efcdSZachary Turner static bool Check(PyObject *py_obj); 470d3bd5b3dSLawrence D'Anna static void Convert(PyRefType &type, PyObject *&py_obj); 4712c1f46dcSZachary Turner 472085328eeSLawrence D'Anna llvm::StringRef GetString() const; // safe, empty string on error 473085328eeSLawrence D'Anna 474085328eeSLawrence D'Anna llvm::Expected<llvm::StringRef> AsUTF8() const; 4752c1f46dcSZachary Turner 476b9c1b51eSKate Stone size_t GetSize() const; 4772c1f46dcSZachary Turner 478085328eeSLawrence D'Anna void SetString(llvm::StringRef string); // safe, null on error 4792c1f46dcSZachary Turner 4802c1f46dcSZachary Turner StructuredData::StringSP CreateStructuredString() const; 4812c1f46dcSZachary Turner }; 4822c1f46dcSZachary Turner 483d3bd5b3dSLawrence D'Anna class PythonInteger : public TypedPythonObject<PythonInteger> { 4842c1f46dcSZachary Turner public: 485d3bd5b3dSLawrence D'Anna using TypedPythonObject::TypedPythonObject; 486edb35d95SEugene Zelenko 487d3bd5b3dSLawrence D'Anna PythonInteger() : TypedPythonObject() {} // MSVC requires this for some reason 488d3bd5b3dSLawrence D'Anna 489d3bd5b3dSLawrence D'Anna explicit PythonInteger(int64_t value); 4902c1f46dcSZachary Turner 49122c8efcdSZachary Turner static bool Check(PyObject *py_obj); 492d3bd5b3dSLawrence D'Anna static void Convert(PyRefType &type, PyObject *&py_obj); 4932c1f46dcSZachary Turner 4942c1f46dcSZachary Turner int64_t GetInteger() const; 4952c1f46dcSZachary Turner 496b9c1b51eSKate Stone void SetInteger(int64_t value); 4972c1f46dcSZachary Turner 4982c1f46dcSZachary Turner StructuredData::IntegerSP CreateStructuredInteger() const; 4992c1f46dcSZachary Turner }; 5002c1f46dcSZachary Turner 501d3bd5b3dSLawrence D'Anna class PythonBoolean : public TypedPythonObject<PythonBoolean> { 502b81d715cSTatyana Krasnukha public: 503d3bd5b3dSLawrence D'Anna using TypedPythonObject::TypedPythonObject; 504b81d715cSTatyana Krasnukha 505d3bd5b3dSLawrence D'Anna explicit PythonBoolean(bool value); 506b81d715cSTatyana Krasnukha 507b81d715cSTatyana Krasnukha static bool Check(PyObject *py_obj); 508b81d715cSTatyana Krasnukha 509b81d715cSTatyana Krasnukha bool GetValue() const; 510b81d715cSTatyana Krasnukha 511b81d715cSTatyana Krasnukha void SetValue(bool value); 512b81d715cSTatyana Krasnukha 513b81d715cSTatyana Krasnukha StructuredData::BooleanSP CreateStructuredBoolean() const; 514b81d715cSTatyana Krasnukha }; 515b81d715cSTatyana Krasnukha 516d3bd5b3dSLawrence D'Anna class PythonList : public TypedPythonObject<PythonList> { 5172c1f46dcSZachary Turner public: 518d3bd5b3dSLawrence D'Anna using TypedPythonObject::TypedPythonObject; 519d3bd5b3dSLawrence D'Anna 520d3bd5b3dSLawrence D'Anna PythonList() : TypedPythonObject() {} // MSVC requires this for some reason 521d3bd5b3dSLawrence D'Anna 52287f47729SZachary Turner explicit PythonList(PyInitialValue value); 52387f47729SZachary Turner explicit PythonList(int list_size); 5242c1f46dcSZachary Turner 52522c8efcdSZachary Turner static bool Check(PyObject *py_obj); 52622c8efcdSZachary Turner 5272c1f46dcSZachary Turner uint32_t GetSize() const; 5282c1f46dcSZachary Turner 5292c1f46dcSZachary Turner PythonObject GetItemAtIndex(uint32_t index) const; 5302c1f46dcSZachary Turner 531f8b22f8fSZachary Turner void SetItemAtIndex(uint32_t index, const PythonObject &object); 5322c1f46dcSZachary Turner 533f8b22f8fSZachary Turner void AppendItem(const PythonObject &object); 5342c1f46dcSZachary Turner 5352c1f46dcSZachary Turner StructuredData::ArraySP CreateStructuredArray() const; 5362c1f46dcSZachary Turner }; 5372c1f46dcSZachary Turner 538d3bd5b3dSLawrence D'Anna class PythonTuple : public TypedPythonObject<PythonTuple> { 539a1405147SZachary Turner public: 540d3bd5b3dSLawrence D'Anna using TypedPythonObject::TypedPythonObject; 541d3bd5b3dSLawrence D'Anna 542a1405147SZachary Turner explicit PythonTuple(PyInitialValue value); 543a1405147SZachary Turner explicit PythonTuple(int tuple_size); 544a1405147SZachary Turner PythonTuple(std::initializer_list<PythonObject> objects); 545a1405147SZachary Turner PythonTuple(std::initializer_list<PyObject *> objects); 546a1405147SZachary Turner 547a1405147SZachary Turner static bool Check(PyObject *py_obj); 548a1405147SZachary Turner 549a1405147SZachary Turner uint32_t GetSize() const; 550a1405147SZachary Turner 551a1405147SZachary Turner PythonObject GetItemAtIndex(uint32_t index) const; 552a1405147SZachary Turner 553a1405147SZachary Turner void SetItemAtIndex(uint32_t index, const PythonObject &object); 554a1405147SZachary Turner 555a1405147SZachary Turner StructuredData::ArraySP CreateStructuredArray() const; 556a1405147SZachary Turner }; 557a1405147SZachary Turner 558d3bd5b3dSLawrence D'Anna class PythonDictionary : public TypedPythonObject<PythonDictionary> { 5592c1f46dcSZachary Turner public: 560d3bd5b3dSLawrence D'Anna using TypedPythonObject::TypedPythonObject; 561edb35d95SEugene Zelenko 562d3bd5b3dSLawrence D'Anna PythonDictionary() : TypedPythonObject() {} // MSVC requires this for some reason 563d3bd5b3dSLawrence D'Anna 564d3bd5b3dSLawrence D'Anna explicit PythonDictionary(PyInitialValue value); 5652c1f46dcSZachary Turner 56622c8efcdSZachary Turner static bool Check(PyObject *py_obj); 56722c8efcdSZachary Turner 5682c1f46dcSZachary Turner uint32_t GetSize() const; 5692c1f46dcSZachary Turner 570f8b22f8fSZachary Turner PythonList GetKeys() const; 5712c1f46dcSZachary Turner 572c86a6acaSLawrence D'Anna PythonObject GetItemForKey(const PythonObject &key) const; // DEPRECATED 573c86a6acaSLawrence D'Anna void SetItemForKey(const PythonObject &key, 574c86a6acaSLawrence D'Anna const PythonObject &value); // DEPRECATED 575c86a6acaSLawrence D'Anna 576c86a6acaSLawrence D'Anna llvm::Expected<PythonObject> GetItem(const PythonObject &key) const; 577722b6189SLawrence D'Anna llvm::Expected<PythonObject> GetItem(const llvm::Twine &key) const; 578c86a6acaSLawrence D'Anna llvm::Error SetItem(const PythonObject &key, const PythonObject &value) const; 579722b6189SLawrence D'Anna llvm::Error SetItem(const llvm::Twine &key, const PythonObject &value) const; 5802c1f46dcSZachary Turner 5812c1f46dcSZachary Turner StructuredData::DictionarySP CreateStructuredDictionary() const; 5822c1f46dcSZachary Turner }; 58387f47729SZachary Turner 584d3bd5b3dSLawrence D'Anna class PythonModule : public TypedPythonObject<PythonModule> { 5857841efbbSZachary Turner public: 586d3bd5b3dSLawrence D'Anna using TypedPythonObject::TypedPythonObject; 5877841efbbSZachary Turner 5887841efbbSZachary Turner static bool Check(PyObject *py_obj); 5897841efbbSZachary Turner 590b9c1b51eSKate Stone static PythonModule BuiltinsModule(); 591a1405147SZachary Turner 592b9c1b51eSKate Stone static PythonModule MainModule(); 593a1405147SZachary Turner 594b9c1b51eSKate Stone static PythonModule AddModule(llvm::StringRef module); 5957841efbbSZachary Turner 596085328eeSLawrence D'Anna // safe, returns invalid on error; 597085328eeSLawrence D'Anna static PythonModule ImportModule(llvm::StringRef name) { 598085328eeSLawrence D'Anna std::string s = name; 599085328eeSLawrence D'Anna auto mod = Import(s.c_str()); 600085328eeSLawrence D'Anna if (!mod) { 601085328eeSLawrence D'Anna llvm::consumeError(mod.takeError()); 602085328eeSLawrence D'Anna return PythonModule(); 603085328eeSLawrence D'Anna } 604085328eeSLawrence D'Anna return std::move(mod.get()); 605085328eeSLawrence D'Anna } 606085328eeSLawrence D'Anna 607722b6189SLawrence D'Anna static llvm::Expected<PythonModule> Import(const llvm::Twine &name); 608085328eeSLawrence D'Anna 609722b6189SLawrence D'Anna llvm::Expected<PythonObject> Get(const llvm::Twine &name); 6102419f1d5SZachary Turner 6117841efbbSZachary Turner PythonDictionary GetDictionary() const; 6127841efbbSZachary Turner }; 6137841efbbSZachary Turner 614d3bd5b3dSLawrence D'Anna class PythonCallable : public TypedPythonObject<PythonCallable> { 615a1405147SZachary Turner public: 616d3bd5b3dSLawrence D'Anna using TypedPythonObject::TypedPythonObject; 617d3bd5b3dSLawrence D'Anna 618b58fb2f4SZachary Turner struct ArgInfo { 6192386537cSLawrence D'Anna /* the largest number of positional arguments this callable 6202386537cSLawrence D'Anna * can accept, or UNBOUNDED, ie UINT_MAX if it's a varargs 6212386537cSLawrence D'Anna * function and can accept an arbitrary number */ 6222386537cSLawrence D'Anna unsigned max_positional_args; 6232386537cSLawrence D'Anna static constexpr unsigned UNBOUNDED = UINT_MAX; // FIXME c++17 inline 624c86a6acaSLawrence D'Anna /* the number of positional arguments, including optional ones, 625c86a6acaSLawrence D'Anna * and excluding varargs. If this is a bound method, then the 626c86a6acaSLawrence D'Anna * count will still include a +1 for self. 627c86a6acaSLawrence D'Anna * 628c86a6acaSLawrence D'Anna * FIXME. That's crazy. This should be replaced with 629c86a6acaSLawrence D'Anna * an accurate min and max for positional args. 630c86a6acaSLawrence D'Anna */ 631c86a6acaSLawrence D'Anna int count; 632c86a6acaSLawrence D'Anna /* does the callable have positional varargs? */ 633c86a6acaSLawrence D'Anna bool has_varargs : 1; // FIXME delete this 634b58fb2f4SZachary Turner }; 635b58fb2f4SZachary Turner 636b9c1b51eSKate Stone static bool Check(PyObject *py_obj); 637a1405147SZachary Turner 638c86a6acaSLawrence D'Anna llvm::Expected<ArgInfo> GetArgInfo() const; 639c86a6acaSLawrence D'Anna 640c86a6acaSLawrence D'Anna llvm::Expected<ArgInfo> GetInitArgInfo() const; 641c86a6acaSLawrence D'Anna 642c86a6acaSLawrence D'Anna ArgInfo GetNumArguments() const; // DEPRECATED 64327a14f19SJim Ingham 64427a14f19SJim Ingham // If the callable is a Py_Class, then find the number of arguments 64527a14f19SJim Ingham // of the __init__ method. 646c86a6acaSLawrence D'Anna ArgInfo GetNumInitArguments() const; // DEPRECATED 647b58fb2f4SZachary Turner 648b9c1b51eSKate Stone PythonObject operator()(); 649a1405147SZachary Turner 650b9c1b51eSKate Stone PythonObject operator()(std::initializer_list<PyObject *> args); 651a1405147SZachary Turner 652b9c1b51eSKate Stone PythonObject operator()(std::initializer_list<PythonObject> args); 653b58fb2f4SZachary Turner 654b58fb2f4SZachary Turner template <typename Arg, typename... Args> 655b9c1b51eSKate Stone PythonObject operator()(const Arg &arg, Args... args) { 656b58fb2f4SZachary Turner return operator()({arg, args...}); 657b58fb2f4SZachary Turner } 658a1405147SZachary Turner }; 659a1405147SZachary Turner 660d3bd5b3dSLawrence D'Anna class PythonFile : public TypedPythonObject<PythonFile> { 6619c40264fSZachary Turner public: 662d3bd5b3dSLawrence D'Anna using TypedPythonObject::TypedPythonObject; 663edb35d95SEugene Zelenko 664d3bd5b3dSLawrence D'Anna PythonFile() : TypedPythonObject() {} // MSVC requires this for some reason 6659c40264fSZachary Turner 6669c40264fSZachary Turner static bool Check(PyObject *py_obj); 6679c40264fSZachary Turner 668d9b553ecSLawrence D'Anna static llvm::Expected<PythonFile> FromFile(File &file, 669d9b553ecSLawrence D'Anna const char *mode = nullptr); 670d9b553ecSLawrence D'Anna 671085328eeSLawrence D'Anna llvm::Expected<lldb::FileSP> ConvertToFile(bool borrowed = false); 672085328eeSLawrence D'Anna llvm::Expected<lldb::FileSP> 673085328eeSLawrence D'Anna ConvertToFileForcingUseOfScriptingIOMethods(bool borrowed = false); 6749c40264fSZachary Turner }; 6759c40264fSZachary Turner 676085328eeSLawrence D'Anna class PythonException : public llvm::ErrorInfo<PythonException> { 677085328eeSLawrence D'Anna private: 678085328eeSLawrence D'Anna PyObject *m_exception_type, *m_exception, *m_traceback; 679085328eeSLawrence D'Anna PyObject *m_repr_bytes; 680085328eeSLawrence D'Anna 681085328eeSLawrence D'Anna public: 682085328eeSLawrence D'Anna static char ID; 683085328eeSLawrence D'Anna const char *toCString() const; 684085328eeSLawrence D'Anna PythonException(const char *caller = nullptr); 685085328eeSLawrence D'Anna void Restore(); 686085328eeSLawrence D'Anna ~PythonException(); 687085328eeSLawrence D'Anna void log(llvm::raw_ostream &OS) const override; 688085328eeSLawrence D'Anna std::error_code convertToErrorCode() const override; 689*04edd189SLawrence D'Anna bool Matches(PyObject *exc) const; 690*04edd189SLawrence D'Anna std::string ReadBacktrace() const; 691085328eeSLawrence D'Anna }; 692085328eeSLawrence D'Anna 693085328eeSLawrence D'Anna // This extracts the underlying T out of an Expected<T> and returns it. 694085328eeSLawrence D'Anna // If the Expected is an Error instead of a T, that error will be converted 695085328eeSLawrence D'Anna // into a python exception, and this will return a default-constructed T. 696085328eeSLawrence D'Anna // 697085328eeSLawrence D'Anna // This is appropriate for use right at the boundary of python calling into 698085328eeSLawrence D'Anna // C++, such as in a SWIG typemap. In such a context you should simply 699085328eeSLawrence D'Anna // check if the returned T is valid, and if it is, return a NULL back 700085328eeSLawrence D'Anna // to python. This will result in the Error being raised as an exception 701085328eeSLawrence D'Anna // from python code's point of view. 702085328eeSLawrence D'Anna // 703085328eeSLawrence D'Anna // For example: 704085328eeSLawrence D'Anna // ``` 705085328eeSLawrence D'Anna // Expected<Foo *> efoop = some_cpp_function(); 706085328eeSLawrence D'Anna // Foo *foop = unwrapOrSetPythonException(efoop); 707085328eeSLawrence D'Anna // if (!foop) 708085328eeSLawrence D'Anna // return NULL; 709085328eeSLawrence D'Anna // do_something(*foop); 710085328eeSLawrence D'Anna // 711085328eeSLawrence D'Anna // If the Error returned was itself created because a python exception was 712085328eeSLawrence D'Anna // raised when C++ code called into python, then the original exception 713085328eeSLawrence D'Anna // will be restored. Otherwise a simple string exception will be raised. 714085328eeSLawrence D'Anna template <typename T> T unwrapOrSetPythonException(llvm::Expected<T> expected) { 715085328eeSLawrence D'Anna if (expected) 716085328eeSLawrence D'Anna return expected.get(); 717085328eeSLawrence D'Anna llvm::handleAllErrors( 718085328eeSLawrence D'Anna expected.takeError(), [](PythonException &E) { E.Restore(); }, 719085328eeSLawrence D'Anna [](const llvm::ErrorInfoBase &E) { 720085328eeSLawrence D'Anna PyErr_SetString(PyExc_Exception, E.message().c_str()); 721085328eeSLawrence D'Anna }); 722085328eeSLawrence D'Anna return T(); 723085328eeSLawrence D'Anna } 724085328eeSLawrence D'Anna 725722b6189SLawrence D'Anna // This is only here to help incrementally migrate old, exception-unsafe 726722b6189SLawrence D'Anna // code. 727722b6189SLawrence D'Anna template <typename T> T unwrapIgnoringErrors(llvm::Expected<T> expected) { 728722b6189SLawrence D'Anna if (expected) 729722b6189SLawrence D'Anna return std::move(expected.get()); 730722b6189SLawrence D'Anna llvm::consumeError(expected.takeError()); 731722b6189SLawrence D'Anna return T(); 732722b6189SLawrence D'Anna } 733722b6189SLawrence D'Anna 734*04edd189SLawrence D'Anna llvm::Expected<PythonObject> runStringOneLine(const llvm::Twine &string, 735*04edd189SLawrence D'Anna const PythonDictionary &globals, 736*04edd189SLawrence D'Anna const PythonDictionary &locals); 737*04edd189SLawrence D'Anna 738*04edd189SLawrence D'Anna llvm::Expected<PythonObject> runStringMultiLine(const llvm::Twine &string, 739*04edd189SLawrence D'Anna const PythonDictionary &globals, 740*04edd189SLawrence D'Anna const PythonDictionary &locals); 741*04edd189SLawrence D'Anna 742*04edd189SLawrence D'Anna // Sometimes the best way to interact with a python interpreter is 743*04edd189SLawrence D'Anna // to run some python code. You construct a PythonScript with 744*04edd189SLawrence D'Anna // script string. The script assigns some function to `_function_` 745*04edd189SLawrence D'Anna // and you get a C++ callable object that calls the python function. 746*04edd189SLawrence D'Anna // 747*04edd189SLawrence D'Anna // Example: 748*04edd189SLawrence D'Anna // 749*04edd189SLawrence D'Anna // const char script[] = R"( 750*04edd189SLawrence D'Anna // def main(x, y): 751*04edd189SLawrence D'Anna // .... 752*04edd189SLawrence D'Anna // )"; 753*04edd189SLawrence D'Anna // 754*04edd189SLawrence D'Anna // Expected<PythonObject> cpp_foo_wrapper(PythonObject x, PythonObject y) { 755*04edd189SLawrence D'Anna // // no need to synchronize access to this global, we already have the GIL 756*04edd189SLawrence D'Anna // static PythonScript foo(script) 757*04edd189SLawrence D'Anna // return foo(x, y); 758*04edd189SLawrence D'Anna // } 759*04edd189SLawrence D'Anna class PythonScript { 760*04edd189SLawrence D'Anna const char *script; 761*04edd189SLawrence D'Anna PythonCallable function; 762*04edd189SLawrence D'Anna 763*04edd189SLawrence D'Anna llvm::Error Init(); 764*04edd189SLawrence D'Anna 765*04edd189SLawrence D'Anna public: 766*04edd189SLawrence D'Anna PythonScript(const char *script) : script(script), function() {} 767*04edd189SLawrence D'Anna 768*04edd189SLawrence D'Anna template <typename... Args> 769*04edd189SLawrence D'Anna llvm::Expected<PythonObject> operator()(Args &&... args) { 770*04edd189SLawrence D'Anna if (llvm::Error error = Init()) 771*04edd189SLawrence D'Anna return std::move(error); 772*04edd189SLawrence D'Anna return function.Call(std::forward<Args>(args)...); 773*04edd189SLawrence D'Anna } 774*04edd189SLawrence D'Anna }; 775*04edd189SLawrence D'Anna 776*04edd189SLawrence D'Anna } // namespace python 7772c1f46dcSZachary Turner } // namespace lldb_private 7782c1f46dcSZachary Turner 779a281b42bSZachary Turner #endif 780d68983e3SPavel Labath 781d68983e3SPavel Labath #endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H 782