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); 283925204cSMed Ismail Bennani virtual ~ScriptedPythonInterface() = default; 293925204cSMed Ismail Bennani 303925204cSMed Ismail Bennani protected: 313925204cSMed Ismail Bennani template <typename T = StructuredData::ObjectSP> 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> 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 413925204cSMed Ismail Bennani auto error_with_message = [&method_name, &error](llvm::StringRef message) { 423925204cSMed Ismail Bennani error.SetErrorStringWithFormatv( 433925204cSMed Ismail Bennani "ScriptedPythonInterface::{0} ({1}) ERROR = {2}", __FUNCTION__, 443925204cSMed Ismail Bennani method_name, message); 453925204cSMed Ismail Bennani return T(); 463925204cSMed Ismail Bennani }; 473925204cSMed Ismail Bennani 483925204cSMed Ismail Bennani if (!m_object_instance_sp) 493925204cSMed Ismail Bennani return error_with_message("Python object ill-formed"); 503925204cSMed Ismail Bennani 513925204cSMed Ismail Bennani Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN, 523925204cSMed Ismail Bennani Locker::FreeLock); 533925204cSMed Ismail Bennani 543925204cSMed Ismail Bennani PythonObject implementor(PyRefType::Borrowed, 553925204cSMed Ismail Bennani (PyObject *)m_object_instance_sp->GetValue()); 563925204cSMed Ismail Bennani 573925204cSMed Ismail Bennani if (!implementor.IsAllocated()) 583925204cSMed Ismail Bennani return error_with_message("Python implementor not allocated."); 593925204cSMed Ismail Bennani 603925204cSMed Ismail Bennani PythonObject pmeth( 613925204cSMed Ismail Bennani PyRefType::Owned, 623925204cSMed Ismail Bennani PyObject_GetAttrString(implementor.get(), method_name.str().c_str())); 633925204cSMed Ismail Bennani 643925204cSMed Ismail Bennani if (PyErr_Occurred()) 653925204cSMed Ismail Bennani PyErr_Clear(); 663925204cSMed Ismail Bennani 673925204cSMed Ismail Bennani if (!pmeth.IsAllocated()) 683925204cSMed Ismail Bennani return error_with_message("Python method not allocated."); 693925204cSMed Ismail Bennani 703925204cSMed Ismail Bennani if (PyCallable_Check(pmeth.get()) == 0) { 713925204cSMed Ismail Bennani if (PyErr_Occurred()) 723925204cSMed Ismail Bennani PyErr_Clear(); 733925204cSMed Ismail Bennani return error_with_message("Python method not callable."); 743925204cSMed Ismail Bennani } 753925204cSMed Ismail Bennani 763925204cSMed Ismail Bennani if (PyErr_Occurred()) 773925204cSMed Ismail Bennani PyErr_Clear(); 783925204cSMed Ismail Bennani 793925204cSMed Ismail Bennani // TODO: make `const char *` when removing support for Python 2. 803925204cSMed Ismail Bennani char *format = nullptr; 813925204cSMed Ismail Bennani std::string format_buffer; 823925204cSMed Ismail Bennani 833925204cSMed Ismail Bennani if (sizeof...(Args) > 0) { 843925204cSMed Ismail Bennani FormatArgs(format_buffer, args...); 853925204cSMed Ismail Bennani // TODO: make `const char *` when removing support for Python 2. 863925204cSMed Ismail Bennani format = const_cast<char *>(format_buffer.c_str()); 873925204cSMed Ismail Bennani } 883925204cSMed Ismail Bennani 893925204cSMed Ismail Bennani // TODO: make `const char *` when removing support for Python 2. 903925204cSMed Ismail Bennani PythonObject py_return( 913925204cSMed Ismail Bennani PyRefType::Owned, 923925204cSMed Ismail Bennani PyObject_CallMethod(implementor.get(), 933925204cSMed Ismail Bennani const_cast<char *>(method_name.data()), format, 943925204cSMed Ismail Bennani args...)); 953925204cSMed Ismail Bennani 963925204cSMed Ismail Bennani if (PyErr_Occurred()) { 973925204cSMed Ismail Bennani PyErr_Print(); 983925204cSMed Ismail Bennani PyErr_Clear(); 993925204cSMed Ismail Bennani return error_with_message("Python method could not be called."); 1003925204cSMed Ismail Bennani } 1013925204cSMed Ismail Bennani 1023925204cSMed Ismail Bennani if (!py_return.IsAllocated()) 1033925204cSMed Ismail Bennani return error_with_message("Returned object is null."); 1043925204cSMed Ismail Bennani 1053925204cSMed Ismail Bennani return ExtractValueFromPythonObject<T>(py_return, error); 1063925204cSMed Ismail Bennani } 1073925204cSMed Ismail Bennani 1083925204cSMed Ismail Bennani Status GetStatusFromMethod(llvm::StringRef method_name); 1093925204cSMed Ismail Bennani 1103925204cSMed Ismail Bennani template <typename T, typename... Args> 1113925204cSMed Ismail Bennani void FormatArgs(std::string &fmt, T arg, Args... args) const { 1123925204cSMed Ismail Bennani FormatArgs(fmt, arg); 1133925204cSMed Ismail Bennani FormatArgs(fmt, args...); 1143925204cSMed Ismail Bennani } 1153925204cSMed Ismail Bennani 1163925204cSMed Ismail Bennani template <typename T> void FormatArgs(std::string &fmt, T arg) const { 1173925204cSMed Ismail Bennani fmt += GetPythonValueFormatString(arg); 1183925204cSMed Ismail Bennani } 1193925204cSMed Ismail Bennani 1203925204cSMed Ismail Bennani void FormatArgs(std::string &fmt) const {} 1213925204cSMed Ismail Bennani 1223925204cSMed Ismail Bennani // The lifetime is managed by the ScriptInterpreter 1233925204cSMed Ismail Bennani ScriptInterpreterPythonImpl &m_interpreter; 1243925204cSMed Ismail Bennani }; 125*5f6f33daSMed Ismail Bennani 126*5f6f33daSMed Ismail Bennani template <> 127*5f6f33daSMed Ismail Bennani Status ScriptedPythonInterface::ExtractValueFromPythonObject<Status>( 128*5f6f33daSMed Ismail Bennani python::PythonObject &p, Status &error); 129*5f6f33daSMed Ismail Bennani 130*5f6f33daSMed Ismail Bennani template <> 131*5f6f33daSMed Ismail Bennani lldb::DataExtractorSP 132*5f6f33daSMed Ismail Bennani ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::DataExtractorSP>( 133*5f6f33daSMed Ismail Bennani python::PythonObject &p, Status &error); 134*5f6f33daSMed Ismail Bennani 1353925204cSMed Ismail Bennani } // namespace lldb_private 1363925204cSMed Ismail Bennani 1373925204cSMed Ismail Bennani #endif // LLDB_ENABLE_PYTHON 1383925204cSMed Ismail Bennani #endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPYTHONINTERFACE_H 139