1 //===-- PythonDataObjects.h--------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 // 10 // !! FIXME FIXME FIXME !! 11 // 12 // Python APIs nearly all can return an exception. They do this 13 // by returning NULL, or -1, or some such value and setting 14 // the exception state with PyErr_Set*(). Exceptions must be 15 // handled before further python API functions are called. Failure 16 // to do so will result in asserts on debug builds of python. 17 // It will also sometimes, but not usually result in crashes of 18 // release builds. 19 // 20 // Nearly all the code in this header does not handle python exceptions 21 // correctly. It should all be converted to return Expected<> or 22 // Error types to capture the exception. 23 // 24 // Everything in this file except functions that return Error or 25 // Expected<> is considered deprecated and should not be 26 // used in new code. If you need to use it, fix it first. 27 // 28 // 29 // TODOs for this file 30 // 31 // * Make all methods safe for exceptions. 32 // 33 // * Eliminate method signatures that must translate exceptions into 34 // empty objects or NULLs. Almost everything here should return 35 // Expected<>. It should be acceptable for certain operations that 36 // can never fail to assert instead, such as the creation of 37 // PythonString from a string literal. 38 // 39 // * Eliminate Reset(), and make all non-default constructors private. 40 // Python objects should be created with Retain<> or Take<>, and they 41 // should be assigned with operator= 42 // 43 // * Eliminate default constructors, make python objects always 44 // nonnull, and use optionals where necessary. 45 // 46 47 48 #ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H 49 #define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H 50 51 #include "lldb/Host/Config.h" 52 53 #if LLDB_ENABLE_PYTHON 54 55 // LLDB Python header must be included first 56 #include "lldb-python.h" 57 58 #include "lldb/Host/File.h" 59 #include "lldb/Utility/StructuredData.h" 60 61 #include "llvm/ADT/ArrayRef.h" 62 63 namespace lldb_private { 64 namespace python { 65 66 class PythonObject; 67 class PythonBytes; 68 class PythonString; 69 class PythonList; 70 class PythonDictionary; 71 class PythonInteger; 72 class PythonException; 73 74 class StructuredPythonObject : public StructuredData::Generic { 75 public: 76 StructuredPythonObject() : StructuredData::Generic() {} 77 78 StructuredPythonObject(void *obj) : StructuredData::Generic(obj) { 79 Py_XINCREF(GetValue()); 80 } 81 82 ~StructuredPythonObject() override { 83 if (Py_IsInitialized()) 84 Py_XDECREF(GetValue()); 85 SetValue(nullptr); 86 } 87 88 bool IsValid() const override { return GetValue() && GetValue() != Py_None; } 89 90 void Serialize(llvm::json::OStream &s) const override; 91 92 private: 93 StructuredPythonObject(const StructuredPythonObject &) = delete; 94 const StructuredPythonObject & 95 operator=(const StructuredPythonObject &) = delete; 96 }; 97 98 enum class PyObjectType { 99 Unknown, 100 None, 101 Boolean, 102 Integer, 103 Dictionary, 104 List, 105 String, 106 Bytes, 107 ByteArray, 108 Module, 109 Callable, 110 Tuple, 111 File 112 }; 113 114 enum class PyRefType { 115 Borrowed, // We are not given ownership of the incoming PyObject. 116 // We cannot safely hold it without calling Py_INCREF. 117 Owned // We have ownership of the incoming PyObject. We should 118 // not call Py_INCREF. 119 }; 120 121 122 // Take a reference that you already own, and turn it into 123 // a PythonObject. 124 // 125 // Most python API methods will return a +1 reference 126 // if they succeed or NULL if and only if 127 // they set an exception. Use this to collect such return 128 // values, after checking for NULL. 129 // 130 // If T is not just PythonObject, then obj must be already be 131 // checked to be of the correct type. 132 template <typename T> T Take(PyObject *obj) { 133 assert(obj); 134 assert(!PyErr_Occurred()); 135 T thing(PyRefType::Owned, obj); 136 assert(thing.IsValid()); 137 return thing; 138 } 139 140 // Retain a reference you have borrowed, and turn it into 141 // a PythonObject. 142 // 143 // A minority of python APIs return a borrowed reference 144 // instead of a +1. They will also return NULL if and only 145 // if they set an exception. Use this to collect such return 146 // values, after checking for NULL. 147 // 148 // If T is not just PythonObject, then obj must be already be 149 // checked to be of the correct type. 150 template <typename T> T Retain(PyObject *obj) { 151 assert(obj); 152 assert(!PyErr_Occurred()); 153 T thing(PyRefType::Borrowed, obj); 154 assert(thing.IsValid()); 155 return thing; 156 } 157 158 // This class can be used like a utility function to convert from 159 // a llvm-friendly Twine into a null-terminated const char *, 160 // which is the form python C APIs want their strings in. 161 // 162 // Example: 163 // const llvm::Twine &some_twine; 164 // PyFoo_Bar(x, y, z, NullTerminated(some_twine)); 165 // 166 // Why a class instead of a function? If the twine isn't already null 167 // terminated, it will need a temporary buffer to copy the string 168 // into. We need that buffer to stick around for the lifetime of the 169 // statement. 170 class NullTerminated { 171 const char *str; 172 llvm::SmallString<32> storage; 173 174 public: 175 NullTerminated(const llvm::Twine &twine) { 176 llvm::StringRef ref = twine.toNullTerminatedStringRef(storage); 177 str = ref.begin(); 178 } 179 operator const char *() { return str; } 180 }; 181 182 inline llvm::Error nullDeref() { 183 return llvm::createStringError(llvm::inconvertibleErrorCode(), 184 "A NULL PyObject* was dereferenced"); 185 } 186 187 inline llvm::Error exception(const char *s = nullptr) { 188 return llvm::make_error<PythonException>(s); 189 } 190 191 inline llvm::Error keyError() { 192 return llvm::createStringError(llvm::inconvertibleErrorCode(), 193 "key not in dict"); 194 } 195 196 #if PY_MAJOR_VERSION < 3 197 // The python 2 API declares some arguments as char* that should 198 // be const char *, but it doesn't actually modify them. 199 inline char *py2_const_cast(const char *s) { return const_cast<char *>(s); } 200 #else 201 inline const char *py2_const_cast(const char *s) { return s; } 202 #endif 203 204 enum class PyInitialValue { Invalid, Empty }; 205 206 template <typename T, typename Enable = void> struct PythonFormat; 207 208 template <> struct PythonFormat<unsigned long long> { 209 static constexpr char format = 'K'; 210 static auto get(unsigned long long value) { return value; } 211 }; 212 213 template <> struct PythonFormat<long long> { 214 static constexpr char format = 'L'; 215 static auto get(long long value) { return value; } 216 }; 217 218 template <> struct PythonFormat<PyObject *> { 219 static constexpr char format = 'O'; 220 static auto get(PyObject *value) { return value; } 221 }; 222 223 template <typename T> 224 struct PythonFormat< 225 T, typename std::enable_if<std::is_base_of<PythonObject, T>::value>::type> { 226 static constexpr char format = 'O'; 227 static auto get(const T &value) { return value.get(); } 228 }; 229 230 class PythonObject { 231 public: 232 PythonObject() = default; 233 234 PythonObject(PyRefType type, PyObject *py_obj) { 235 m_py_obj = py_obj; 236 // If this is a borrowed reference, we need to convert it to 237 // an owned reference by incrementing it. If it is an owned 238 // reference (for example the caller allocated it with PyDict_New() 239 // then we must *not* increment it. 240 if (m_py_obj && Py_IsInitialized() && type == PyRefType::Borrowed) 241 Py_XINCREF(m_py_obj); 242 } 243 244 PythonObject(const PythonObject &rhs) 245 : PythonObject(PyRefType::Borrowed, rhs.m_py_obj) {} 246 247 PythonObject(PythonObject &&rhs) { 248 m_py_obj = rhs.m_py_obj; 249 rhs.m_py_obj = nullptr; 250 } 251 252 ~PythonObject() { Reset(); } 253 254 void Reset() { 255 if (m_py_obj && Py_IsInitialized()) 256 Py_DECREF(m_py_obj); 257 m_py_obj = nullptr; 258 } 259 260 void Dump() const { 261 if (m_py_obj) 262 _PyObject_Dump(m_py_obj); 263 else 264 puts("NULL"); 265 } 266 267 void Dump(Stream &strm) const; 268 269 PyObject *get() const { return m_py_obj; } 270 271 PyObject *release() { 272 PyObject *result = m_py_obj; 273 m_py_obj = nullptr; 274 return result; 275 } 276 277 PythonObject &operator=(PythonObject other) { 278 Reset(); 279 m_py_obj = std::exchange(other.m_py_obj, nullptr); 280 return *this; 281 } 282 283 PyObjectType GetObjectType() const; 284 285 PythonString Repr() const; 286 287 PythonString Str() const; 288 289 static PythonObject ResolveNameWithDictionary(llvm::StringRef name, 290 const PythonDictionary &dict); 291 292 template <typename T> 293 static T ResolveNameWithDictionary(llvm::StringRef name, 294 const PythonDictionary &dict) { 295 return ResolveNameWithDictionary(name, dict).AsType<T>(); 296 } 297 298 PythonObject ResolveName(llvm::StringRef name) const; 299 300 template <typename T> T ResolveName(llvm::StringRef name) const { 301 return ResolveName(name).AsType<T>(); 302 } 303 304 bool HasAttribute(llvm::StringRef attribute) const; 305 306 PythonObject GetAttributeValue(llvm::StringRef attribute) const; 307 308 bool IsNone() const { return m_py_obj == Py_None; } 309 310 bool IsValid() const { return m_py_obj != nullptr; } 311 312 bool IsAllocated() const { return IsValid() && !IsNone(); } 313 314 explicit operator bool() const { return IsValid() && !IsNone(); } 315 316 template <typename T> T AsType() const { 317 if (!T::Check(m_py_obj)) 318 return T(); 319 return T(PyRefType::Borrowed, m_py_obj); 320 } 321 322 StructuredData::ObjectSP CreateStructuredObject() const; 323 324 template <typename... T> 325 llvm::Expected<PythonObject> CallMethod(const char *name, 326 const T &... t) const { 327 const char format[] = {'(', PythonFormat<T>::format..., ')', 0}; 328 PyObject *obj = 329 PyObject_CallMethod(m_py_obj, py2_const_cast(name), 330 py2_const_cast(format), PythonFormat<T>::get(t)...); 331 if (!obj) 332 return exception(); 333 return python::Take<PythonObject>(obj); 334 } 335 336 template <typename... T> 337 llvm::Expected<PythonObject> Call(const T &... t) const { 338 const char format[] = {'(', PythonFormat<T>::format..., ')', 0}; 339 PyObject *obj = PyObject_CallFunction(m_py_obj, py2_const_cast(format), 340 PythonFormat<T>::get(t)...); 341 if (!obj) 342 return exception(); 343 return python::Take<PythonObject>(obj); 344 } 345 346 llvm::Expected<PythonObject> GetAttribute(const llvm::Twine &name) const { 347 if (!m_py_obj) 348 return nullDeref(); 349 PyObject *obj = PyObject_GetAttrString(m_py_obj, NullTerminated(name)); 350 if (!obj) 351 return exception(); 352 return python::Take<PythonObject>(obj); 353 } 354 355 llvm::Expected<bool> IsTrue() { 356 if (!m_py_obj) 357 return nullDeref(); 358 int r = PyObject_IsTrue(m_py_obj); 359 if (r < 0) 360 return exception(); 361 return !!r; 362 } 363 364 llvm::Expected<long long> AsLongLong() const; 365 366 llvm::Expected<long long> AsUnsignedLongLong() const; 367 368 // wraps on overflow, instead of raising an error. 369 llvm::Expected<unsigned long long> AsModuloUnsignedLongLong() const; 370 371 llvm::Expected<bool> IsInstance(const PythonObject &cls) { 372 if (!m_py_obj || !cls.IsValid()) 373 return nullDeref(); 374 int r = PyObject_IsInstance(m_py_obj, cls.get()); 375 if (r < 0) 376 return exception(); 377 return !!r; 378 } 379 380 protected: 381 PyObject *m_py_obj = nullptr; 382 }; 383 384 385 // This is why C++ needs monads. 386 template <typename T> llvm::Expected<T> As(llvm::Expected<PythonObject> &&obj) { 387 if (!obj) 388 return obj.takeError(); 389 if (!T::Check(obj.get().get())) 390 return llvm::createStringError(llvm::inconvertibleErrorCode(), 391 "type error"); 392 return T(PyRefType::Borrowed, std::move(obj.get().get())); 393 } 394 395 template <> llvm::Expected<bool> As<bool>(llvm::Expected<PythonObject> &&obj); 396 397 template <> 398 llvm::Expected<long long> As<long long>(llvm::Expected<PythonObject> &&obj); 399 400 template <> 401 llvm::Expected<unsigned long long> 402 As<unsigned long long>(llvm::Expected<PythonObject> &&obj); 403 404 template <> 405 llvm::Expected<std::string> As<std::string>(llvm::Expected<PythonObject> &&obj); 406 407 408 template <class T> class TypedPythonObject : public PythonObject { 409 public: 410 // override to perform implicit type conversions on Reset 411 // This can be eliminated once we drop python 2 support. 412 static void Convert(PyRefType &type, PyObject *&py_obj) {} 413 414 TypedPythonObject(PyRefType type, PyObject *py_obj) { 415 if (!py_obj) 416 return; 417 T::Convert(type, py_obj); 418 if (T::Check(py_obj)) 419 PythonObject::operator=(PythonObject(type, py_obj)); 420 else if (type == PyRefType::Owned) 421 Py_DECREF(py_obj); 422 } 423 424 TypedPythonObject() = default; 425 }; 426 427 class PythonBytes : public TypedPythonObject<PythonBytes> { 428 public: 429 using TypedPythonObject::TypedPythonObject; 430 explicit PythonBytes(llvm::ArrayRef<uint8_t> bytes); 431 PythonBytes(const uint8_t *bytes, size_t length); 432 433 static bool Check(PyObject *py_obj); 434 435 llvm::ArrayRef<uint8_t> GetBytes() const; 436 437 size_t GetSize() const; 438 439 void SetBytes(llvm::ArrayRef<uint8_t> stringbytes); 440 441 StructuredData::StringSP CreateStructuredString() const; 442 }; 443 444 class PythonByteArray : public TypedPythonObject<PythonByteArray> { 445 public: 446 using TypedPythonObject::TypedPythonObject; 447 explicit PythonByteArray(llvm::ArrayRef<uint8_t> bytes); 448 PythonByteArray(const uint8_t *bytes, size_t length); 449 PythonByteArray(const PythonBytes &object); 450 451 static bool Check(PyObject *py_obj); 452 453 llvm::ArrayRef<uint8_t> GetBytes() const; 454 455 size_t GetSize() const; 456 457 void SetBytes(llvm::ArrayRef<uint8_t> stringbytes); 458 459 StructuredData::StringSP CreateStructuredString() const; 460 }; 461 462 class PythonString : public TypedPythonObject<PythonString> { 463 public: 464 using TypedPythonObject::TypedPythonObject; 465 static llvm::Expected<PythonString> FromUTF8(llvm::StringRef string); 466 467 PythonString() : TypedPythonObject() {} // MSVC requires this for some reason 468 469 explicit PythonString(llvm::StringRef string); // safe, null on error 470 471 static bool Check(PyObject *py_obj); 472 static void Convert(PyRefType &type, PyObject *&py_obj); 473 474 llvm::StringRef GetString() const; // safe, empty string on error 475 476 llvm::Expected<llvm::StringRef> AsUTF8() const; 477 478 size_t GetSize() const; 479 480 void SetString(llvm::StringRef string); // safe, null on error 481 482 StructuredData::StringSP CreateStructuredString() const; 483 }; 484 485 class PythonInteger : public TypedPythonObject<PythonInteger> { 486 public: 487 using TypedPythonObject::TypedPythonObject; 488 489 PythonInteger() : TypedPythonObject() {} // MSVC requires this for some reason 490 491 explicit PythonInteger(int64_t value); 492 493 static bool Check(PyObject *py_obj); 494 static void Convert(PyRefType &type, PyObject *&py_obj); 495 496 void SetInteger(int64_t value); 497 498 StructuredData::IntegerSP CreateStructuredInteger() const; 499 }; 500 501 class PythonBoolean : public TypedPythonObject<PythonBoolean> { 502 public: 503 using TypedPythonObject::TypedPythonObject; 504 505 explicit PythonBoolean(bool value); 506 507 static bool Check(PyObject *py_obj); 508 509 bool GetValue() const; 510 511 void SetValue(bool value); 512 513 StructuredData::BooleanSP CreateStructuredBoolean() const; 514 }; 515 516 class PythonList : public TypedPythonObject<PythonList> { 517 public: 518 using TypedPythonObject::TypedPythonObject; 519 520 PythonList() : TypedPythonObject() {} // MSVC requires this for some reason 521 522 explicit PythonList(PyInitialValue value); 523 explicit PythonList(int list_size); 524 525 static bool Check(PyObject *py_obj); 526 527 uint32_t GetSize() const; 528 529 PythonObject GetItemAtIndex(uint32_t index) const; 530 531 void SetItemAtIndex(uint32_t index, const PythonObject &object); 532 533 void AppendItem(const PythonObject &object); 534 535 StructuredData::ArraySP CreateStructuredArray() const; 536 }; 537 538 class PythonTuple : public TypedPythonObject<PythonTuple> { 539 public: 540 using TypedPythonObject::TypedPythonObject; 541 542 explicit PythonTuple(PyInitialValue value); 543 explicit PythonTuple(int tuple_size); 544 PythonTuple(std::initializer_list<PythonObject> objects); 545 PythonTuple(std::initializer_list<PyObject *> objects); 546 547 static bool Check(PyObject *py_obj); 548 549 uint32_t GetSize() const; 550 551 PythonObject GetItemAtIndex(uint32_t index) const; 552 553 void SetItemAtIndex(uint32_t index, const PythonObject &object); 554 555 StructuredData::ArraySP CreateStructuredArray() const; 556 }; 557 558 class PythonDictionary : public TypedPythonObject<PythonDictionary> { 559 public: 560 using TypedPythonObject::TypedPythonObject; 561 562 PythonDictionary() : TypedPythonObject() {} // MSVC requires this for some reason 563 564 explicit PythonDictionary(PyInitialValue value); 565 566 static bool Check(PyObject *py_obj); 567 568 uint32_t GetSize() const; 569 570 PythonList GetKeys() const; 571 572 PythonObject GetItemForKey(const PythonObject &key) const; // DEPRECATED 573 void SetItemForKey(const PythonObject &key, 574 const PythonObject &value); // DEPRECATED 575 576 llvm::Expected<PythonObject> GetItem(const PythonObject &key) const; 577 llvm::Expected<PythonObject> GetItem(const llvm::Twine &key) const; 578 llvm::Error SetItem(const PythonObject &key, const PythonObject &value) const; 579 llvm::Error SetItem(const llvm::Twine &key, const PythonObject &value) const; 580 581 StructuredData::DictionarySP CreateStructuredDictionary() const; 582 }; 583 584 class PythonModule : public TypedPythonObject<PythonModule> { 585 public: 586 using TypedPythonObject::TypedPythonObject; 587 588 static bool Check(PyObject *py_obj); 589 590 static PythonModule BuiltinsModule(); 591 592 static PythonModule MainModule(); 593 594 static PythonModule AddModule(llvm::StringRef module); 595 596 // safe, returns invalid on error; 597 static PythonModule ImportModule(llvm::StringRef name) { 598 std::string s = std::string(name); 599 auto mod = Import(s.c_str()); 600 if (!mod) { 601 llvm::consumeError(mod.takeError()); 602 return PythonModule(); 603 } 604 return std::move(mod.get()); 605 } 606 607 static llvm::Expected<PythonModule> Import(const llvm::Twine &name); 608 609 llvm::Expected<PythonObject> Get(const llvm::Twine &name); 610 611 PythonDictionary GetDictionary() const; 612 }; 613 614 class PythonCallable : public TypedPythonObject<PythonCallable> { 615 public: 616 using TypedPythonObject::TypedPythonObject; 617 618 struct ArgInfo { 619 /* the largest number of positional arguments this callable 620 * can accept, or UNBOUNDED, ie UINT_MAX if it's a varargs 621 * function and can accept an arbitrary number */ 622 unsigned max_positional_args; 623 static constexpr unsigned UNBOUNDED = UINT_MAX; // FIXME c++17 inline 624 }; 625 626 static bool Check(PyObject *py_obj); 627 628 llvm::Expected<ArgInfo> GetArgInfo() const; 629 630 PythonObject operator()(); 631 632 PythonObject operator()(std::initializer_list<PyObject *> args); 633 634 PythonObject operator()(std::initializer_list<PythonObject> args); 635 636 template <typename Arg, typename... Args> 637 PythonObject operator()(const Arg &arg, Args... args) { 638 return operator()({arg, args...}); 639 } 640 }; 641 642 class PythonFile : public TypedPythonObject<PythonFile> { 643 public: 644 using TypedPythonObject::TypedPythonObject; 645 646 PythonFile() : TypedPythonObject() {} // MSVC requires this for some reason 647 648 static bool Check(PyObject *py_obj); 649 650 static llvm::Expected<PythonFile> FromFile(File &file, 651 const char *mode = nullptr); 652 653 llvm::Expected<lldb::FileSP> ConvertToFile(bool borrowed = false); 654 llvm::Expected<lldb::FileSP> 655 ConvertToFileForcingUseOfScriptingIOMethods(bool borrowed = false); 656 }; 657 658 class PythonException : public llvm::ErrorInfo<PythonException> { 659 private: 660 PyObject *m_exception_type, *m_exception, *m_traceback; 661 PyObject *m_repr_bytes; 662 663 public: 664 static char ID; 665 const char *toCString() const; 666 PythonException(const char *caller = nullptr); 667 void Restore(); 668 ~PythonException(); 669 void log(llvm::raw_ostream &OS) const override; 670 std::error_code convertToErrorCode() const override; 671 bool Matches(PyObject *exc) const; 672 std::string ReadBacktrace() const; 673 }; 674 675 // This extracts the underlying T out of an Expected<T> and returns it. 676 // If the Expected is an Error instead of a T, that error will be converted 677 // into a python exception, and this will return a default-constructed T. 678 // 679 // This is appropriate for use right at the boundary of python calling into 680 // C++, such as in a SWIG typemap. In such a context you should simply 681 // check if the returned T is valid, and if it is, return a NULL back 682 // to python. This will result in the Error being raised as an exception 683 // from python code's point of view. 684 // 685 // For example: 686 // ``` 687 // Expected<Foo *> efoop = some_cpp_function(); 688 // Foo *foop = unwrapOrSetPythonException(efoop); 689 // if (!foop) 690 // return NULL; 691 // do_something(*foop); 692 // 693 // If the Error returned was itself created because a python exception was 694 // raised when C++ code called into python, then the original exception 695 // will be restored. Otherwise a simple string exception will be raised. 696 template <typename T> T unwrapOrSetPythonException(llvm::Expected<T> expected) { 697 if (expected) 698 return expected.get(); 699 llvm::handleAllErrors( 700 expected.takeError(), [](PythonException &E) { E.Restore(); }, 701 [](const llvm::ErrorInfoBase &E) { 702 PyErr_SetString(PyExc_Exception, E.message().c_str()); 703 }); 704 return T(); 705 } 706 707 // This is only here to help incrementally migrate old, exception-unsafe 708 // code. 709 template <typename T> T unwrapIgnoringErrors(llvm::Expected<T> expected) { 710 if (expected) 711 return std::move(expected.get()); 712 llvm::consumeError(expected.takeError()); 713 return T(); 714 } 715 716 llvm::Expected<PythonObject> runStringOneLine(const llvm::Twine &string, 717 const PythonDictionary &globals, 718 const PythonDictionary &locals); 719 720 llvm::Expected<PythonObject> runStringMultiLine(const llvm::Twine &string, 721 const PythonDictionary &globals, 722 const PythonDictionary &locals); 723 724 // Sometimes the best way to interact with a python interpreter is 725 // to run some python code. You construct a PythonScript with 726 // script string. The script assigns some function to `_function_` 727 // and you get a C++ callable object that calls the python function. 728 // 729 // Example: 730 // 731 // const char script[] = R"( 732 // def main(x, y): 733 // .... 734 // )"; 735 // 736 // Expected<PythonObject> cpp_foo_wrapper(PythonObject x, PythonObject y) { 737 // // no need to synchronize access to this global, we already have the GIL 738 // static PythonScript foo(script) 739 // return foo(x, y); 740 // } 741 class PythonScript { 742 const char *script; 743 PythonCallable function; 744 745 llvm::Error Init(); 746 747 public: 748 PythonScript(const char *script) : script(script), function() {} 749 750 template <typename... Args> 751 llvm::Expected<PythonObject> operator()(Args &&... args) { 752 if (llvm::Error error = Init()) 753 return std::move(error); 754 return function.Call(std::forward<Args>(args)...); 755 } 756 }; 757 758 } // namespace python 759 } // namespace lldb_private 760 761 #endif 762 763 #endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H 764