llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-lldb Author: Chelsea Cassanova (chelcassanova) <details> <summary>Changes</summary> This commit refactors the typemaps and static functions used in the SWIG typemaps and wrappers to be in their own SWIG files that are included in the main `python.swig` file. --- Full diff: https://github.com/llvm/llvm-project/pull/95318.diff 5 Files Affected: - (added) lldb/bindings/python/python-callbacks-typemaps.swig (+119) - (added) lldb/bindings/python/python-callbacks-wrapper.swig (+101) - (modified) lldb/bindings/python/python-typemaps.swig (-116) - (modified) lldb/bindings/python/python-wrapper.swig (-96) - (modified) lldb/bindings/python/python.swig (+2) ``````````diff diff --git a/lldb/bindings/python/python-callbacks-typemaps.swig b/lldb/bindings/python/python-callbacks-typemaps.swig new file mode 100644 index 0000000000000..71f01c1144557 --- /dev/null +++ b/lldb/bindings/python/python-callbacks-typemaps.swig @@ -0,0 +1,119 @@ +/* + Typemaps specific to callback functions in LLDB. If editing this file + use the Python C API to access Python objects instead of using PythonDataObjects. +*/ + +// For Log::LogOutputCallback +%typemap(in) (lldb::LogOutputCallback log_callback, void *baton) { + if (!($input == Py_None || + PyCallable_Check(reinterpret_cast<PyObject *>($input)))) { + PyErr_SetString(PyExc_TypeError, "Need a callable object or None!"); + SWIG_fail; + } + + // FIXME (filcab): We can't currently check if our callback is already + // LLDBSwigPythonCallPythonLogOutputCallback (to DECREF the previous + // baton) nor can we just remove all traces of a callback, if we want to + // revert to a file logging mechanism. + + // Don't lose the callback reference + Py_INCREF($input); + $1 = LLDBSwigPythonCallPythonLogOutputCallback; + $2 = $input; +} + +%typemap(typecheck) (lldb::LogOutputCallback log_callback, void *baton) { + $1 = $input == Py_None; + $1 = $1 || PyCallable_Check(reinterpret_cast<PyObject *>($input)); +} + +// For lldb::SBDebuggerDestroyCallback +%typemap(in) (lldb::SBDebuggerDestroyCallback destroy_callback, void *baton) { + if (!($input == Py_None || + PyCallable_Check(reinterpret_cast<PyObject *>($input)))) { + PyErr_SetString(PyExc_TypeError, "Need a callable object or None!"); + SWIG_fail; + } + + // FIXME (filcab): We can't currently check if our callback is already + // LLDBSwigPythonCallPythonSBDebuggerTerminateCallback (to DECREF the previous + // baton) nor can we just remove all traces of a callback, if we want to + // revert to a file logging mechanism. + + // Don't lose the callback reference + Py_INCREF($input); + $1 = LLDBSwigPythonCallPythonSBDebuggerTerminateCallback; + $2 = $input; +} + +%typemap(typecheck) (lldb::SBDebuggerDestroyCallback destroy_callback, void *baton) { + $1 = $input == Py_None; + $1 = $1 || PyCallable_Check(reinterpret_cast<PyObject *>($input)); +} + +%typemap(in) (lldb::CommandOverrideCallback callback, void *baton) { + if (!($input == Py_None || + PyCallable_Check(reinterpret_cast<PyObject *>($input)))) { + PyErr_SetString(PyExc_TypeError, "Need a callable object or None!"); + SWIG_fail; + } + + // Don't lose the callback reference + Py_INCREF($input); + $1 = LLDBSwigPythonCallPythonSBCommandInterpreterSetCommandOverrideCallback; + $2 = $input; +} +%typemap(typecheck) (lldb::CommandOverrideCallback callback, void *baton) { + $1 = $input == Py_None; + $1 = $1 || PyCallable_Check(reinterpret_cast<PyObject *>($input)); +} +// For lldb::SBPlatformLocateModuleCallback +%typemap(in) (lldb::SBPlatformLocateModuleCallback callback, + void *callback_baton) { + if (!($input == Py_None || + PyCallable_Check(reinterpret_cast<PyObject *>($input)))) { + PyErr_SetString(PyExc_TypeError, "Need a callable object or None!"); + SWIG_fail; + } + + if ($input == Py_None) { + $1 = nullptr; + $2 = nullptr; + } else { + PythonCallable callable = Retain<PythonCallable>($input); + if (!callable.IsValid()) { + PyErr_SetString(PyExc_TypeError, "Need a valid callable object"); + SWIG_fail; + } + + llvm::Expected<PythonCallable::ArgInfo> arg_info = callable.GetArgInfo(); + if (!arg_info) { + PyErr_SetString(PyExc_TypeError, + ("Could not get arguments: " + + llvm::toString(arg_info.takeError())).c_str()); + SWIG_fail; + } + + if (arg_info.get().max_positional_args != 3) { + PyErr_SetString(PyExc_TypeError, "Expected 3 argument callable object"); + SWIG_fail; + } + + // NOTE: When this is called multiple times, this will leak the Python + // callable object as other callbacks, because this does not call Py_DECREF + // the object. But it should be almost zero impact since this method is + // expected to be called only once. + + // Don't lose the callback reference + Py_INCREF($input); + + $1 = LLDBSwigPythonCallLocateModuleCallback; + $2 = $input; + } +} + +%typemap(typecheck) (lldb::SBPlatformLocateModuleCallback callback, + void *callback_baton) { + $1 = $input == Py_None; + $1 = $1 || PyCallable_Check(reinterpret_cast<PyObject *>($input)); +} diff --git a/lldb/bindings/python/python-callbacks-wrapper.swig b/lldb/bindings/python/python-callbacks-wrapper.swig new file mode 100644 index 0000000000000..0b48436ef3102 --- /dev/null +++ b/lldb/bindings/python/python-callbacks-wrapper.swig @@ -0,0 +1,101 @@ +/* + Wrapper that holds static functions used for callback typemaps in LLDB. +*/ + +%header %{ +// For the LogOutputCallback functions +static void LLDBSwigPythonCallPythonLogOutputCallback(const char *str, + void *baton) { + if (baton != Py_None) { + SWIG_PYTHON_THREAD_BEGIN_BLOCK; + PyObject *result = PyObject_CallFunction( + reinterpret_cast<PyObject *>(baton), const_cast<char *>("s"), str); + Py_XDECREF(result); + SWIG_PYTHON_THREAD_END_BLOCK; + } +} + +// For DebuggerTerminateCallback functions +static void LLDBSwigPythonCallPythonSBDebuggerTerminateCallback(lldb::user_id_t debugger_id, + void *baton) { + if (baton != Py_None) { + SWIG_PYTHON_THREAD_BEGIN_BLOCK; + PyObject *result = PyObject_CallFunction( + reinterpret_cast<PyObject *>(baton), const_cast<char *>("l"), debugger_id); + Py_XDECREF(result); + SWIG_PYTHON_THREAD_END_BLOCK; + } +} + +static bool LLDBSwigPythonCallPythonSBCommandInterpreterSetCommandOverrideCallback(void *baton, const char **argv) { + bool ret_val = false; + if (baton != Py_None) { + SWIG_PYTHON_THREAD_BEGIN_BLOCK; + // Create a PyList of items since we're going to pass it to the callback as a tuple + // of arguments. + PyObject *py_argv = PyList_New(0); + for (const char **arg = argv; arg && *arg; arg++) { + std::string arg_string = *arg; + PyObject *py_string = PyUnicode_FromStringAndSize(arg_string.c_str(), arg_string.size()); + PyList_Append(py_argv, py_string); + } + + PyObject *result = PyObject_CallObject( + reinterpret_cast<PyObject *>(baton), PyList_AsTuple(py_argv)); + ret_val = result ? PyObject_IsTrue(result) : false; + Py_XDECREF(result); + SWIG_PYTHON_THREAD_END_BLOCK; + } + return ret_val; +} + +static SBError LLDBSwigPythonCallLocateModuleCallback( + void *callback_baton, const SBModuleSpec &module_spec_sb, + SBFileSpec &module_file_spec_sb, SBFileSpec &symbol_file_spec_sb) { + SWIG_Python_Thread_Block swig_thread_block; + + PyErr_Cleaner py_err_cleaner(true); + PythonObject module_spec_arg = SWIGBridge::ToSWIGWrapper( + std::make_unique<SBModuleSpec>(module_spec_sb)); + PythonObject module_file_spec_arg = SWIGBridge::ToSWIGWrapper( + std::make_unique<SBFileSpec>(module_file_spec_sb)); + PythonObject symbol_file_spec_arg = SWIGBridge::ToSWIGWrapper( + std::make_unique<SBFileSpec>(symbol_file_spec_sb)); + + PythonCallable callable = + Retain<PythonCallable>(reinterpret_cast<PyObject *>(callback_baton)); + if (!callable.IsValid()) { + return SBError("The callback callable is not valid."); + } + + PythonObject result = callable(module_spec_arg, module_file_spec_arg, + symbol_file_spec_arg); + + if (!result.IsAllocated()) + return SBError("No result."); + lldb::SBError *sb_error_ptr = nullptr; + if (SWIG_ConvertPtr(result.get(), (void **)&sb_error_ptr, + SWIGTYPE_p_lldb__SBError, 0) == -1) { + return SBError("Result is not SBError."); + } + + if (sb_error_ptr->Success()) { + lldb::SBFileSpec *sb_module_file_spec_ptr = nullptr; + if (SWIG_ConvertPtr(module_file_spec_arg.get(), + (void **)&sb_module_file_spec_ptr, + SWIGTYPE_p_lldb__SBFileSpec, 0) == -1) + return SBError("module_file_spec is not SBFileSpec."); + + lldb::SBFileSpec *sb_symbol_file_spec_ptr = nullptr; + if (SWIG_ConvertPtr(symbol_file_spec_arg.get(), + (void **)&sb_symbol_file_spec_ptr, + SWIGTYPE_p_lldb__SBFileSpec, 0) == -1) + return SBError("symbol_file_spec is not SBFileSpec."); + + module_file_spec_sb = *sb_module_file_spec_ptr; + symbol_file_spec_sb = *sb_symbol_file_spec_ptr; + } + + return *sb_error_ptr; +} +%} diff --git a/lldb/bindings/python/python-typemaps.swig b/lldb/bindings/python/python-typemaps.swig index c39594c7df041..3af54826e8248 100644 --- a/lldb/bindings/python/python-typemaps.swig +++ b/lldb/bindings/python/python-typemaps.swig @@ -427,71 +427,6 @@ template <> bool SetNumberFromPyObject<double>(double &number, PyObject *obj) { free($1); } -// For Log::LogOutputCallback -%typemap(in) (lldb::LogOutputCallback log_callback, void *baton) { - if (!($input == Py_None || - PyCallable_Check(reinterpret_cast<PyObject *>($input)))) { - PyErr_SetString(PyExc_TypeError, "Need a callable object or None!"); - SWIG_fail; - } - - // FIXME (filcab): We can't currently check if our callback is already - // LLDBSwigPythonCallPythonLogOutputCallback (to DECREF the previous - // baton) nor can we just remove all traces of a callback, if we want to - // revert to a file logging mechanism. - - // Don't lose the callback reference - Py_INCREF($input); - $1 = LLDBSwigPythonCallPythonLogOutputCallback; - $2 = $input; -} - -%typemap(typecheck) (lldb::LogOutputCallback log_callback, void *baton) { - $1 = $input == Py_None; - $1 = $1 || PyCallable_Check(reinterpret_cast<PyObject *>($input)); -} - -// For lldb::SBDebuggerDestroyCallback -%typemap(in) (lldb::SBDebuggerDestroyCallback destroy_callback, void *baton) { - if (!($input == Py_None || - PyCallable_Check(reinterpret_cast<PyObject *>($input)))) { - PyErr_SetString(PyExc_TypeError, "Need a callable object or None!"); - SWIG_fail; - } - - // FIXME (filcab): We can't currently check if our callback is already - // LLDBSwigPythonCallPythonSBDebuggerTerminateCallback (to DECREF the previous - // baton) nor can we just remove all traces of a callback, if we want to - // revert to a file logging mechanism. - - // Don't lose the callback reference - Py_INCREF($input); - $1 = LLDBSwigPythonCallPythonSBDebuggerTerminateCallback; - $2 = $input; -} - -%typemap(typecheck) (lldb::SBDebuggerDestroyCallback destroy_callback, void *baton) { - $1 = $input == Py_None; - $1 = $1 || PyCallable_Check(reinterpret_cast<PyObject *>($input)); -} - -%typemap(in) (lldb::CommandOverrideCallback callback, void *baton) { - if (!($input == Py_None || - PyCallable_Check(reinterpret_cast<PyObject *>($input)))) { - PyErr_SetString(PyExc_TypeError, "Need a callable object or None!"); - SWIG_fail; - } - - // Don't lose the callback reference. - Py_INCREF($input); - $1 = LLDBSwigPythonCallPythonSBCommandInterpreterSetCommandOverrideCallback; - $2 = $input; -} -%typemap(typecheck) (lldb::CommandOverrideCallback callback, void *baton) { - $1 = $input == Py_None; - $1 = $1 || PyCallable_Check(reinterpret_cast<PyObject *>($input)); -} - %typemap(in) lldb::FileSP { PythonFile py_file(PyRefType::Borrowed, $input); if (!py_file) { @@ -661,54 +596,3 @@ template <> bool SetNumberFromPyObject<double>(double &number, PyObject *obj) { return NULL; } } - -// For lldb::SBPlatformLocateModuleCallback -%typemap(in) (lldb::SBPlatformLocateModuleCallback callback, - void *callback_baton) { - if (!($input == Py_None || - PyCallable_Check(reinterpret_cast<PyObject *>($input)))) { - PyErr_SetString(PyExc_TypeError, "Need a callable object or None!"); - SWIG_fail; - } - - if ($input == Py_None) { - $1 = nullptr; - $2 = nullptr; - } else { - PythonCallable callable = Retain<PythonCallable>($input); - if (!callable.IsValid()) { - PyErr_SetString(PyExc_TypeError, "Need a valid callable object"); - SWIG_fail; - } - - llvm::Expected<PythonCallable::ArgInfo> arg_info = callable.GetArgInfo(); - if (!arg_info) { - PyErr_SetString(PyExc_TypeError, - ("Could not get arguments: " + - llvm::toString(arg_info.takeError())).c_str()); - SWIG_fail; - } - - if (arg_info.get().max_positional_args != 3) { - PyErr_SetString(PyExc_TypeError, "Expected 3 argument callable object"); - SWIG_fail; - } - - // NOTE: When this is called multiple times, this will leak the Python - // callable object as other callbacks, because this does not call Py_DECREF - // the object. But it should be almost zero impact since this method is - // expected to be called only once. - - // Don't lose the callback reference - Py_INCREF($input); - - $1 = LLDBSwigPythonCallLocateModuleCallback; - $2 = $input; - } -} - -%typemap(typecheck) (lldb::SBPlatformLocateModuleCallback callback, - void *callback_baton) { - $1 = $input == Py_None; - $1 = $1 || PyCallable_Check(reinterpret_cast<PyObject *>($input)); -} diff --git a/lldb/bindings/python/python-wrapper.swig b/lldb/bindings/python/python-wrapper.swig index bd3de8ce5d46c..f2cdc39626dc0 100644 --- a/lldb/bindings/python/python-wrapper.swig +++ b/lldb/bindings/python/python-wrapper.swig @@ -1074,100 +1074,4 @@ lldb::ValueObjectSP lldb_private::python::SWIGBridge::LLDBSWIGPython_GetValueObj } return valobj_sp; } - -// For the LogOutputCallback functions -static void LLDBSwigPythonCallPythonLogOutputCallback(const char *str, - void *baton) { - if (baton != Py_None) { - SWIG_PYTHON_THREAD_BEGIN_BLOCK; - PyObject *result = PyObject_CallFunction( - reinterpret_cast<PyObject *>(baton), const_cast<char *>("s"), str); - Py_XDECREF(result); - SWIG_PYTHON_THREAD_END_BLOCK; - } -} - -// For DebuggerTerminateCallback functions -static void LLDBSwigPythonCallPythonSBDebuggerTerminateCallback(lldb::user_id_t debugger_id, - void *baton) { - if (baton != Py_None) { - SWIG_PYTHON_THREAD_BEGIN_BLOCK; - PyObject *result = PyObject_CallFunction( - reinterpret_cast<PyObject *>(baton), const_cast<char *>("l"), debugger_id); - Py_XDECREF(result); - SWIG_PYTHON_THREAD_END_BLOCK; - } -} - -static bool LLDBSwigPythonCallPythonSBCommandInterpreterSetCommandOverrideCallback(void *baton, const char **argv) { - bool ret_val = false; - if (baton != Py_None) { - SWIG_PYTHON_THREAD_BEGIN_BLOCK; - // Create a PyList of items since we're going to pass it to the callback as a tuple - // of arguments. - PyObject *py_argv = PyList_New(0); - for (const char **arg = argv; arg && *arg; arg++) { - std::string arg_string = *arg; - PyObject *py_string = PyUnicode_FromStringAndSize(arg_string.c_str(), arg_string.size()); - PyList_Append(py_argv, py_string); - } - - PyObject *result = PyObject_CallObject( - reinterpret_cast<PyObject *>(baton), PyList_AsTuple(py_argv)); - ret_val = result ? PyObject_IsTrue(result) : false; - Py_XDECREF(result); - SWIG_PYTHON_THREAD_END_BLOCK; - } - return ret_val; -} - -static SBError LLDBSwigPythonCallLocateModuleCallback( - void *callback_baton, const SBModuleSpec &module_spec_sb, - SBFileSpec &module_file_spec_sb, SBFileSpec &symbol_file_spec_sb) { - SWIG_Python_Thread_Block swig_thread_block; - - PyErr_Cleaner py_err_cleaner(true); - PythonObject module_spec_arg = SWIGBridge::ToSWIGWrapper( - std::make_unique<SBModuleSpec>(module_spec_sb)); - PythonObject module_file_spec_arg = SWIGBridge::ToSWIGWrapper( - std::make_unique<SBFileSpec>(module_file_spec_sb)); - PythonObject symbol_file_spec_arg = SWIGBridge::ToSWIGWrapper( - std::make_unique<SBFileSpec>(symbol_file_spec_sb)); - - PythonCallable callable = - Retain<PythonCallable>(reinterpret_cast<PyObject *>(callback_baton)); - if (!callable.IsValid()) { - return SBError("The callback callable is not valid."); - } - - PythonObject result = callable(module_spec_arg, module_file_spec_arg, - symbol_file_spec_arg); - - if (!result.IsAllocated()) - return SBError("No result."); - lldb::SBError *sb_error_ptr = nullptr; - if (SWIG_ConvertPtr(result.get(), (void **)&sb_error_ptr, - SWIGTYPE_p_lldb__SBError, 0) == -1) { - return SBError("Result is not SBError."); - } - - if (sb_error_ptr->Success()) { - lldb::SBFileSpec *sb_module_file_spec_ptr = nullptr; - if (SWIG_ConvertPtr(module_file_spec_arg.get(), - (void **)&sb_module_file_spec_ptr, - SWIGTYPE_p_lldb__SBFileSpec, 0) == -1) - return SBError("module_file_spec is not SBFileSpec."); - - lldb::SBFileSpec *sb_symbol_file_spec_ptr = nullptr; - if (SWIG_ConvertPtr(symbol_file_spec_arg.get(), - (void **)&sb_symbol_file_spec_ptr, - SWIGTYPE_p_lldb__SBFileSpec, 0) == -1) - return SBError("symbol_file_spec is not SBFileSpec."); - - module_file_spec_sb = *sb_module_file_spec_ptr; - symbol_file_spec_sb = *sb_symbol_file_spec_ptr; - } - - return *sb_error_ptr; -} %} diff --git a/lldb/bindings/python/python.swig b/lldb/bindings/python/python.swig index 278c0eed2bab2..e4944b3ebe413 100644 --- a/lldb/bindings/python/python.swig +++ b/lldb/bindings/python/python.swig @@ -110,6 +110,7 @@ def lldb_iter(obj, getsize, getelem): %include <std_string.i> %include "python-typemaps.swig" +%include "python-callbacks-typemaps.swig" %include "macros.swig" %include "headers.swig" @@ -125,6 +126,7 @@ using namespace lldb; %include "interfaces.swig" %include "python-extensions.swig" %include "python-wrapper.swig" +%include "python-callbacks-wrapper.swig" %pythoncode%{ debugger_unique_id = 0 `````````` </details> https://github.com/llvm/llvm-project/pull/95318 _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits