[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