[Lldb-commits] [lldb] [lldb][swig] Refactor callback typemaps and functions (PR #95318)
via lldb-commits
lldb-commits at lists.llvm.org
Wed Jun 12 14:49:19 PDT 2024
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
More information about the lldb-commits
mailing list