1 //===-- ScriptedPythonInterface.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 #ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPYTHONINTERFACE_H 10 #define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPYTHONINTERFACE_H 11 12 #include "lldb/Host/Config.h" 13 14 #if LLDB_ENABLE_PYTHON 15 16 #include "lldb/Interpreter/ScriptedInterface.h" 17 #include "lldb/Utility/DataBufferHeap.h" 18 19 #include "PythonDataObjects.h" 20 #include "SWIGPythonBridge.h" 21 #include "ScriptInterpreterPythonImpl.h" 22 23 namespace lldb_private { 24 class ScriptInterpreterPythonImpl; 25 class ScriptedPythonInterface : virtual public ScriptedInterface { 26 public: 27 ScriptedPythonInterface(ScriptInterpreterPythonImpl &interpreter); 28 virtual ~ScriptedPythonInterface() = default; 29 30 protected: 31 template <typename T = StructuredData::ObjectSP> 32 T ExtractValueFromPythonObject(python::PythonObject &p, Status &error) { 33 return p.CreateStructuredObject(); 34 } 35 36 template <typename T = StructuredData::ObjectSP, typename... Args> 37 T Dispatch(llvm::StringRef method_name, Status &error, Args... args) { 38 using namespace python; 39 using Locker = ScriptInterpreterPythonImpl::Locker; 40 41 auto error_with_message = [&method_name, &error](llvm::StringRef message) { 42 error.SetErrorStringWithFormatv( 43 "ScriptedPythonInterface::{0} ({1}) ERROR = {2}", __FUNCTION__, 44 method_name, message); 45 return T(); 46 }; 47 48 if (!m_object_instance_sp) 49 return error_with_message("Python object ill-formed"); 50 51 Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN, 52 Locker::FreeLock); 53 54 PythonObject implementor(PyRefType::Borrowed, 55 (PyObject *)m_object_instance_sp->GetValue()); 56 57 if (!implementor.IsAllocated()) 58 return error_with_message("Python implementor not allocated."); 59 60 PythonObject pmeth( 61 PyRefType::Owned, 62 PyObject_GetAttrString(implementor.get(), method_name.str().c_str())); 63 64 if (PyErr_Occurred()) 65 PyErr_Clear(); 66 67 if (!pmeth.IsAllocated()) 68 return error_with_message("Python method not allocated."); 69 70 if (PyCallable_Check(pmeth.get()) == 0) { 71 if (PyErr_Occurred()) 72 PyErr_Clear(); 73 return error_with_message("Python method not callable."); 74 } 75 76 if (PyErr_Occurred()) 77 PyErr_Clear(); 78 79 // TODO: make `const char *` when removing support for Python 2. 80 char *format = nullptr; 81 std::string format_buffer; 82 83 if (sizeof...(Args) > 0) { 84 FormatArgs(format_buffer, args...); 85 // TODO: make `const char *` when removing support for Python 2. 86 format = const_cast<char *>(format_buffer.c_str()); 87 } 88 89 // TODO: make `const char *` when removing support for Python 2. 90 PythonObject py_return( 91 PyRefType::Owned, 92 PyObject_CallMethod(implementor.get(), 93 const_cast<char *>(method_name.data()), format, 94 args...)); 95 96 if (PyErr_Occurred()) { 97 PyErr_Print(); 98 PyErr_Clear(); 99 return error_with_message("Python method could not be called."); 100 } 101 102 if (!py_return.IsAllocated()) 103 return error_with_message("Returned object is null."); 104 105 return ExtractValueFromPythonObject<T>(py_return, error); 106 } 107 108 Status GetStatusFromMethod(llvm::StringRef method_name); 109 110 template <typename T, typename... Args> 111 void FormatArgs(std::string &fmt, T arg, Args... args) const { 112 FormatArgs(fmt, arg); 113 FormatArgs(fmt, args...); 114 } 115 116 template <typename T> void FormatArgs(std::string &fmt, T arg) const { 117 fmt += GetPythonValueFormatString(arg); 118 } 119 120 void FormatArgs(std::string &fmt) const {} 121 122 // The lifetime is managed by the ScriptInterpreter 123 ScriptInterpreterPythonImpl &m_interpreter; 124 }; 125 126 template <> 127 Status ScriptedPythonInterface::ExtractValueFromPythonObject<Status>( 128 python::PythonObject &p, Status &error); 129 130 template <> 131 lldb::DataExtractorSP 132 ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::DataExtractorSP>( 133 python::PythonObject &p, Status &error); 134 135 } // namespace lldb_private 136 137 #endif // LLDB_ENABLE_PYTHON 138 #endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPYTHONINTERFACE_H 139