13925204cSMed Ismail Bennani //===-- ScriptedPythonInterface.h -------------------------------*- C++ -*-===// 23925204cSMed Ismail Bennani // 33925204cSMed Ismail Bennani // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 43925204cSMed Ismail Bennani // See https://llvm.org/LICENSE.txt for license information. 53925204cSMed Ismail Bennani // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 63925204cSMed Ismail Bennani // 73925204cSMed Ismail Bennani //===----------------------------------------------------------------------===// 83925204cSMed Ismail Bennani 93925204cSMed Ismail Bennani #ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPYTHONINTERFACE_H 103925204cSMed Ismail Bennani #define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPYTHONINTERFACE_H 113925204cSMed Ismail Bennani 123925204cSMed Ismail Bennani #include "lldb/Host/Config.h" 133925204cSMed Ismail Bennani 143925204cSMed Ismail Bennani #if LLDB_ENABLE_PYTHON 153925204cSMed Ismail Bennani 163925204cSMed Ismail Bennani #include "lldb/Interpreter/ScriptedInterface.h" 173925204cSMed Ismail Bennani #include "lldb/Utility/DataBufferHeap.h" 183925204cSMed Ismail Bennani 193925204cSMed Ismail Bennani #include "PythonDataObjects.h" 203925204cSMed Ismail Bennani #include "SWIGPythonBridge.h" 213925204cSMed Ismail Bennani #include "ScriptInterpreterPythonImpl.h" 223925204cSMed Ismail Bennani 233925204cSMed Ismail Bennani namespace lldb_private { 243925204cSMed Ismail Bennani class ScriptInterpreterPythonImpl; 253925204cSMed Ismail Bennani class ScriptedPythonInterface : virtual public ScriptedInterface { 263925204cSMed Ismail Bennani public: 273925204cSMed Ismail Bennani ScriptedPythonInterface(ScriptInterpreterPythonImpl &interpreter); 28*99166339SJonas Devlieghere ~ScriptedPythonInterface() override = default; 293925204cSMed Ismail Bennani 303925204cSMed Ismail Bennani protected: 313925204cSMed Ismail Bennani template <typename T = StructuredData::ObjectSP> ExtractValueFromPythonObject(python::PythonObject & p,Status & error)323925204cSMed Ismail Bennani T ExtractValueFromPythonObject(python::PythonObject &p, Status &error) { 333925204cSMed Ismail Bennani return p.CreateStructuredObject(); 343925204cSMed Ismail Bennani } 353925204cSMed Ismail Bennani 363925204cSMed Ismail Bennani template <typename T = StructuredData::ObjectSP, typename... Args> Dispatch(llvm::StringRef method_name,Status & error,Args...args)373925204cSMed Ismail Bennani T Dispatch(llvm::StringRef method_name, Status &error, Args... args) { 383925204cSMed Ismail Bennani using namespace python; 393925204cSMed Ismail Bennani using Locker = ScriptInterpreterPythonImpl::Locker; 403925204cSMed Ismail Bennani 4159d8dd79SMed Ismail Bennani std::string caller_signature = 4288a941baSMed Ismail Bennani llvm::Twine(LLVM_PRETTY_FUNCTION + llvm::Twine(" (") + 4359d8dd79SMed Ismail Bennani llvm::Twine(method_name) + llvm::Twine(")")) 4459d8dd79SMed Ismail Bennani .str(); 453925204cSMed Ismail Bennani if (!m_object_instance_sp) 4659d8dd79SMed Ismail Bennani return ErrorWithMessage<T>(caller_signature, "Python object ill-formed", 4759d8dd79SMed Ismail Bennani error); 483925204cSMed Ismail Bennani 493925204cSMed Ismail Bennani Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN, 503925204cSMed Ismail Bennani Locker::FreeLock); 513925204cSMed Ismail Bennani 523925204cSMed Ismail Bennani PythonObject implementor(PyRefType::Borrowed, 533925204cSMed Ismail Bennani (PyObject *)m_object_instance_sp->GetValue()); 543925204cSMed Ismail Bennani 553925204cSMed Ismail Bennani if (!implementor.IsAllocated()) 5659d8dd79SMed Ismail Bennani return ErrorWithMessage<T>(caller_signature, 5759d8dd79SMed Ismail Bennani "Python implementor not allocated.", error); 583925204cSMed Ismail Bennani 593925204cSMed Ismail Bennani PythonObject pmeth( 603925204cSMed Ismail Bennani PyRefType::Owned, 613925204cSMed Ismail Bennani PyObject_GetAttrString(implementor.get(), method_name.str().c_str())); 623925204cSMed Ismail Bennani 633925204cSMed Ismail Bennani if (PyErr_Occurred()) 643925204cSMed Ismail Bennani PyErr_Clear(); 653925204cSMed Ismail Bennani 663925204cSMed Ismail Bennani if (!pmeth.IsAllocated()) 6759d8dd79SMed Ismail Bennani return ErrorWithMessage<T>(caller_signature, 6859d8dd79SMed Ismail Bennani "Python method not allocated.", error); 693925204cSMed Ismail Bennani 703925204cSMed Ismail Bennani if (PyCallable_Check(pmeth.get()) == 0) { 713925204cSMed Ismail Bennani if (PyErr_Occurred()) 723925204cSMed Ismail Bennani PyErr_Clear(); 7359d8dd79SMed Ismail Bennani return ErrorWithMessage<T>(caller_signature, 7459d8dd79SMed Ismail Bennani "Python method not callable.", error); 753925204cSMed Ismail Bennani } 763925204cSMed Ismail Bennani 773925204cSMed Ismail Bennani if (PyErr_Occurred()) 783925204cSMed Ismail Bennani PyErr_Clear(); 793925204cSMed Ismail Bennani 803925204cSMed Ismail Bennani // TODO: make `const char *` when removing support for Python 2. 813925204cSMed Ismail Bennani char *format = nullptr; 823925204cSMed Ismail Bennani std::string format_buffer; 833925204cSMed Ismail Bennani 843925204cSMed Ismail Bennani if (sizeof...(Args) > 0) { 853925204cSMed Ismail Bennani FormatArgs(format_buffer, args...); 863925204cSMed Ismail Bennani // TODO: make `const char *` when removing support for Python 2. 873925204cSMed Ismail Bennani format = const_cast<char *>(format_buffer.c_str()); 883925204cSMed Ismail Bennani } 893925204cSMed Ismail Bennani 903925204cSMed Ismail Bennani // TODO: make `const char *` when removing support for Python 2. 913925204cSMed Ismail Bennani PythonObject py_return( 923925204cSMed Ismail Bennani PyRefType::Owned, 933925204cSMed Ismail Bennani PyObject_CallMethod(implementor.get(), 943925204cSMed Ismail Bennani const_cast<char *>(method_name.data()), format, 953925204cSMed Ismail Bennani args...)); 963925204cSMed Ismail Bennani 973925204cSMed Ismail Bennani if (PyErr_Occurred()) { 983925204cSMed Ismail Bennani PyErr_Print(); 993925204cSMed Ismail Bennani PyErr_Clear(); 10059d8dd79SMed Ismail Bennani return ErrorWithMessage<T>(caller_signature, 10159d8dd79SMed Ismail Bennani "Python method could not be called.", error); 1023925204cSMed Ismail Bennani } 1033925204cSMed Ismail Bennani 1043925204cSMed Ismail Bennani if (!py_return.IsAllocated()) 10559d8dd79SMed Ismail Bennani return ErrorWithMessage<T>(caller_signature, "Returned object is null.", 10659d8dd79SMed Ismail Bennani error); 1073925204cSMed Ismail Bennani 1083925204cSMed Ismail Bennani return ExtractValueFromPythonObject<T>(py_return, error); 1093925204cSMed Ismail Bennani } 1103925204cSMed Ismail Bennani 1113925204cSMed Ismail Bennani Status GetStatusFromMethod(llvm::StringRef method_name); 1123925204cSMed Ismail Bennani 1133925204cSMed Ismail Bennani template <typename T, typename... Args> FormatArgs(std::string & fmt,T arg,Args...args)1143925204cSMed Ismail Bennani void FormatArgs(std::string &fmt, T arg, Args... args) const { 1153925204cSMed Ismail Bennani FormatArgs(fmt, arg); 1163925204cSMed Ismail Bennani FormatArgs(fmt, args...); 1173925204cSMed Ismail Bennani } 1183925204cSMed Ismail Bennani FormatArgs(std::string & fmt,T arg)1193925204cSMed Ismail Bennani template <typename T> void FormatArgs(std::string &fmt, T arg) const { 1203925204cSMed Ismail Bennani fmt += GetPythonValueFormatString(arg); 1213925204cSMed Ismail Bennani } 1223925204cSMed Ismail Bennani FormatArgs(std::string & fmt)1233925204cSMed Ismail Bennani void FormatArgs(std::string &fmt) const {} 1243925204cSMed Ismail Bennani 1253925204cSMed Ismail Bennani // The lifetime is managed by the ScriptInterpreter 1263925204cSMed Ismail Bennani ScriptInterpreterPythonImpl &m_interpreter; 1273925204cSMed Ismail Bennani }; 1285f6f33daSMed Ismail Bennani 1295f6f33daSMed Ismail Bennani template <> 13070665844SMed Ismail Bennani StructuredData::ArraySP 13170665844SMed Ismail Bennani ScriptedPythonInterface::ExtractValueFromPythonObject<StructuredData::ArraySP>( 13270665844SMed Ismail Bennani python::PythonObject &p, Status &error); 13370665844SMed Ismail Bennani 13470665844SMed Ismail Bennani template <> 13559d8dd79SMed Ismail Bennani StructuredData::DictionarySP 13659d8dd79SMed Ismail Bennani ScriptedPythonInterface::ExtractValueFromPythonObject< 13759d8dd79SMed Ismail Bennani StructuredData::DictionarySP>(python::PythonObject &p, Status &error); 13859d8dd79SMed Ismail Bennani 13959d8dd79SMed Ismail Bennani template <> 1405f6f33daSMed Ismail Bennani Status ScriptedPythonInterface::ExtractValueFromPythonObject<Status>( 1415f6f33daSMed Ismail Bennani python::PythonObject &p, Status &error); 1425f6f33daSMed Ismail Bennani 1435f6f33daSMed Ismail Bennani template <> 1445f6f33daSMed Ismail Bennani lldb::DataExtractorSP 1455f6f33daSMed Ismail Bennani ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::DataExtractorSP>( 1465f6f33daSMed Ismail Bennani python::PythonObject &p, Status &error); 1475f6f33daSMed Ismail Bennani 148a758c9f7SMed Ismail Bennani template <> 149a758c9f7SMed Ismail Bennani llvm::Optional<MemoryRegionInfo> 150a758c9f7SMed Ismail Bennani ScriptedPythonInterface::ExtractValueFromPythonObject< 151a758c9f7SMed Ismail Bennani llvm::Optional<MemoryRegionInfo>>(python::PythonObject &p, Status &error); 152a758c9f7SMed Ismail Bennani 1533925204cSMed Ismail Bennani } // namespace lldb_private 1543925204cSMed Ismail Bennani 1553925204cSMed Ismail Bennani #endif // LLDB_ENABLE_PYTHON 1563925204cSMed Ismail Bennani #endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPYTHONINTERFACE_H 157