From c0981da47d5696fe36474fcf86b4ce03ae3ff818 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Fri, 19 Nov 2021 21:06:13 +0100 Subject: Vendor import of llvm-project main llvmorg-14-init-10186-gff7f2cfa959b. --- .../Python/ScriptedPythonInterface.h | 151 +++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h (limited to 'lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h') diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h new file mode 100644 index 000000000000..da112eb72022 --- /dev/null +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h @@ -0,0 +1,151 @@ +//===-- ScriptedPythonInterface.h -------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPYTHONINTERFACE_H +#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPYTHONINTERFACE_H + +#include "lldb/Host/Config.h" + +#if LLDB_ENABLE_PYTHON + +#include "lldb/Interpreter/ScriptedInterface.h" +#include "lldb/Utility/DataBufferHeap.h" + +#include "PythonDataObjects.h" +#include "SWIGPythonBridge.h" +#include "ScriptInterpreterPythonImpl.h" + +namespace lldb_private { +class ScriptInterpreterPythonImpl; +class ScriptedPythonInterface : virtual public ScriptedInterface { +public: + ScriptedPythonInterface(ScriptInterpreterPythonImpl &interpreter); + virtual ~ScriptedPythonInterface() = default; + +protected: + template + T ExtractValueFromPythonObject(python::PythonObject &p, Status &error) { + return p.CreateStructuredObject(); + } + + template + T Dispatch(llvm::StringRef method_name, Status &error, Args... args) { + using namespace python; + using Locker = ScriptInterpreterPythonImpl::Locker; + + std::string caller_signature = + llvm::Twine(LLVM_PRETTY_FUNCTION + llvm::Twine(" (") + + llvm::Twine(method_name) + llvm::Twine(")")) + .str(); + if (!m_object_instance_sp) + return ErrorWithMessage(caller_signature, "Python object ill-formed", + error); + + Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN, + Locker::FreeLock); + + PythonObject implementor(PyRefType::Borrowed, + (PyObject *)m_object_instance_sp->GetValue()); + + if (!implementor.IsAllocated()) + return ErrorWithMessage(caller_signature, + "Python implementor not allocated.", error); + + PythonObject pmeth( + PyRefType::Owned, + PyObject_GetAttrString(implementor.get(), method_name.str().c_str())); + + if (PyErr_Occurred()) + PyErr_Clear(); + + if (!pmeth.IsAllocated()) + return ErrorWithMessage(caller_signature, + "Python method not allocated.", error); + + if (PyCallable_Check(pmeth.get()) == 0) { + if (PyErr_Occurred()) + PyErr_Clear(); + return ErrorWithMessage(caller_signature, + "Python method not callable.", error); + } + + if (PyErr_Occurred()) + PyErr_Clear(); + + // TODO: make `const char *` when removing support for Python 2. + char *format = nullptr; + std::string format_buffer; + + if (sizeof...(Args) > 0) { + FormatArgs(format_buffer, args...); + // TODO: make `const char *` when removing support for Python 2. + format = const_cast(format_buffer.c_str()); + } + + // TODO: make `const char *` when removing support for Python 2. + PythonObject py_return( + PyRefType::Owned, + PyObject_CallMethod(implementor.get(), + const_cast(method_name.data()), format, + args...)); + + if (PyErr_Occurred()) { + PyErr_Print(); + PyErr_Clear(); + return ErrorWithMessage(caller_signature, + "Python method could not be called.", error); + } + + if (!py_return.IsAllocated()) + return ErrorWithMessage(caller_signature, "Returned object is null.", + error); + + return ExtractValueFromPythonObject(py_return, error); + } + + Status GetStatusFromMethod(llvm::StringRef method_name); + + template + void FormatArgs(std::string &fmt, T arg, Args... args) const { + FormatArgs(fmt, arg); + FormatArgs(fmt, args...); + } + + template void FormatArgs(std::string &fmt, T arg) const { + fmt += GetPythonValueFormatString(arg); + } + + void FormatArgs(std::string &fmt) const {} + + // The lifetime is managed by the ScriptInterpreter + ScriptInterpreterPythonImpl &m_interpreter; +}; + +template <> +StructuredData::DictionarySP +ScriptedPythonInterface::ExtractValueFromPythonObject< + StructuredData::DictionarySP>(python::PythonObject &p, Status &error); + +template <> +Status ScriptedPythonInterface::ExtractValueFromPythonObject( + python::PythonObject &p, Status &error); + +template <> +lldb::DataExtractorSP +ScriptedPythonInterface::ExtractValueFromPythonObject( + python::PythonObject &p, Status &error); + +template <> +llvm::Optional +ScriptedPythonInterface::ExtractValueFromPythonObject< + llvm::Optional>(python::PythonObject &p, Status &error); + +} // namespace lldb_private + +#endif // LLDB_ENABLE_PYTHON +#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPYTHONINTERFACE_H -- cgit v1.2.3