forked from OSchip/llvm-project
157 lines
5.1 KiB
C++
157 lines
5.1 KiB
C++
//===-- 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);
|
|
~ScriptedPythonInterface() override = default;
|
|
|
|
protected:
|
|
template <typename T = StructuredData::ObjectSP>
|
|
T ExtractValueFromPythonObject(python::PythonObject &p, Status &error) {
|
|
return p.CreateStructuredObject();
|
|
}
|
|
|
|
template <typename T = StructuredData::ObjectSP, typename... Args>
|
|
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<T>(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<T>(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<T>(caller_signature,
|
|
"Python method not allocated.", error);
|
|
|
|
if (PyCallable_Check(pmeth.get()) == 0) {
|
|
if (PyErr_Occurred())
|
|
PyErr_Clear();
|
|
return ErrorWithMessage<T>(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<char *>(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<char *>(method_name.data()), format,
|
|
args...));
|
|
|
|
if (PyErr_Occurred()) {
|
|
PyErr_Print();
|
|
PyErr_Clear();
|
|
return ErrorWithMessage<T>(caller_signature,
|
|
"Python method could not be called.", error);
|
|
}
|
|
|
|
if (!py_return.IsAllocated())
|
|
return ErrorWithMessage<T>(caller_signature, "Returned object is null.",
|
|
error);
|
|
|
|
return ExtractValueFromPythonObject<T>(py_return, error);
|
|
}
|
|
|
|
Status GetStatusFromMethod(llvm::StringRef method_name);
|
|
|
|
template <typename T, typename... Args>
|
|
void FormatArgs(std::string &fmt, T arg, Args... args) const {
|
|
FormatArgs(fmt, arg);
|
|
FormatArgs(fmt, args...);
|
|
}
|
|
|
|
template <typename T> 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::ArraySP
|
|
ScriptedPythonInterface::ExtractValueFromPythonObject<StructuredData::ArraySP>(
|
|
python::PythonObject &p, Status &error);
|
|
|
|
template <>
|
|
StructuredData::DictionarySP
|
|
ScriptedPythonInterface::ExtractValueFromPythonObject<
|
|
StructuredData::DictionarySP>(python::PythonObject &p, Status &error);
|
|
|
|
template <>
|
|
Status ScriptedPythonInterface::ExtractValueFromPythonObject<Status>(
|
|
python::PythonObject &p, Status &error);
|
|
|
|
template <>
|
|
lldb::DataExtractorSP
|
|
ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::DataExtractorSP>(
|
|
python::PythonObject &p, Status &error);
|
|
|
|
template <>
|
|
llvm::Optional<MemoryRegionInfo>
|
|
ScriptedPythonInterface::ExtractValueFromPythonObject<
|
|
llvm::Optional<MemoryRegionInfo>>(python::PythonObject &p, Status &error);
|
|
|
|
} // namespace lldb_private
|
|
|
|
#endif // LLDB_ENABLE_PYTHON
|
|
#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPYTHONINTERFACE_H
|