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 <> 37 Status ExtractValueFromPythonObject<Status>(python::PythonObject &p, 38 Status &error) { 39 if (lldb::SBError *sb_error = reinterpret_cast<lldb::SBError *>( 40 LLDBSWIGPython_CastPyObjectToSBError(p.get()))) 41 error = m_interpreter.GetStatusFromSBError(*sb_error); 42 else 43 error.SetErrorString("Couldn't cast lldb::SBError to lldb::Status."); 44 45 return error; 46 } 47 48 template <> 49 lldb::DataExtractorSP 50 ExtractValueFromPythonObject<lldb::DataExtractorSP>(python::PythonObject &p, 51 Status &error) { 52 lldb::SBData *sb_data = reinterpret_cast<lldb::SBData *>( 53 LLDBSWIGPython_CastPyObjectToSBData(p.get())); 54 55 if (!sb_data) { 56 error.SetErrorString("Couldn't cast lldb::SBError to lldb::Status."); 57 return nullptr; 58 } 59 60 return m_interpreter.GetDataExtractorFromSBData(*sb_data); 61 } 62 63 template <typename T = StructuredData::ObjectSP, typename... Args> 64 T Dispatch(llvm::StringRef method_name, Status &error, Args... args) { 65 using namespace python; 66 using Locker = ScriptInterpreterPythonImpl::Locker; 67 68 auto error_with_message = [&method_name, &error](llvm::StringRef message) { 69 error.SetErrorStringWithFormatv( 70 "ScriptedPythonInterface::{0} ({1}) ERROR = {2}", __FUNCTION__, 71 method_name, message); 72 return T(); 73 }; 74 75 if (!m_object_instance_sp) 76 return error_with_message("Python object ill-formed"); 77 78 Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN, 79 Locker::FreeLock); 80 81 PythonObject implementor(PyRefType::Borrowed, 82 (PyObject *)m_object_instance_sp->GetValue()); 83 84 if (!implementor.IsAllocated()) 85 return error_with_message("Python implementor not allocated."); 86 87 PythonObject pmeth( 88 PyRefType::Owned, 89 PyObject_GetAttrString(implementor.get(), method_name.str().c_str())); 90 91 if (PyErr_Occurred()) 92 PyErr_Clear(); 93 94 if (!pmeth.IsAllocated()) 95 return error_with_message("Python method not allocated."); 96 97 if (PyCallable_Check(pmeth.get()) == 0) { 98 if (PyErr_Occurred()) 99 PyErr_Clear(); 100 return error_with_message("Python method not callable."); 101 } 102 103 if (PyErr_Occurred()) 104 PyErr_Clear(); 105 106 // TODO: make `const char *` when removing support for Python 2. 107 char *format = nullptr; 108 std::string format_buffer; 109 110 if (sizeof...(Args) > 0) { 111 FormatArgs(format_buffer, args...); 112 // TODO: make `const char *` when removing support for Python 2. 113 format = const_cast<char *>(format_buffer.c_str()); 114 } 115 116 // TODO: make `const char *` when removing support for Python 2. 117 PythonObject py_return( 118 PyRefType::Owned, 119 PyObject_CallMethod(implementor.get(), 120 const_cast<char *>(method_name.data()), format, 121 args...)); 122 123 if (PyErr_Occurred()) { 124 PyErr_Print(); 125 PyErr_Clear(); 126 return error_with_message("Python method could not be called."); 127 } 128 129 if (!py_return.IsAllocated()) 130 return error_with_message("Returned object is null."); 131 132 return ExtractValueFromPythonObject<T>(py_return, error); 133 } 134 135 Status GetStatusFromMethod(llvm::StringRef method_name); 136 137 template <typename T, typename... Args> 138 void FormatArgs(std::string &fmt, T arg, Args... args) const { 139 FormatArgs(fmt, arg); 140 FormatArgs(fmt, args...); 141 } 142 143 template <typename T> void FormatArgs(std::string &fmt, T arg) const { 144 fmt += GetPythonValueFormatString(arg); 145 } 146 147 void FormatArgs(std::string &fmt) const {} 148 149 // The lifetime is managed by the ScriptInterpreter 150 ScriptInterpreterPythonImpl &m_interpreter; 151 }; 152 } // namespace lldb_private 153 154 #endif // LLDB_ENABLE_PYTHON 155 #endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPYTHONINTERFACE_H 156