Added a typemap and wrappers for SBInputReader callbacks
Now it's possible to use SBInputReader callbacks in Python.
We leak the callback object, unfortunately. A __del__ method can be added
to SBInputReader, but we have no way to check the callback function that
is on the reader. So we can't call Py_DECREF on it when we have our
PythonCallback function. One way to do it is to assume that reified
SBInputReaders always have a Python callback (and always call Py_DECREF).
Another one is to add methods or properties to SBInputReader (or make the
m_callback_function property public).
git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@162356 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/scripts/Python/python-extensions.swig b/scripts/Python/python-extensions.swig
index cd8f1cf..24f06a1 100644
--- a/scripts/Python/python-extensions.swig
+++ b/scripts/Python/python-extensions.swig
@@ -25,7 +25,6 @@
return PyString_FromStringAndSize (desc, desc_len);
else
return PyString_FromString("");
-
}
}
%extend lldb::SBBreakpoint {
@@ -485,6 +484,16 @@
}
}
+// %extend lldb::SBInputReader {
+// // FIXME: m_callback_function is private and we have no other
+// // way to access it.
+// PyObject *lldb::SBInputReader::__del__ (){
+// // Only call Py_XDECREF if we have a Python object (or NULL)
+// if (LLDBSwigPythonCallSBInputReaderCallback == $self->m_callback_function)
+// Py_XDECREF($self->m_callback_baton);
+// }
+// }
+
%pythoncode %{
class declaration(object):
diff --git a/scripts/Python/python-typemaps.swig b/scripts/Python/python-typemaps.swig
index c269795..e212d3f 100644
--- a/scripts/Python/python-typemaps.swig
+++ b/scripts/Python/python-typemaps.swig
@@ -350,6 +350,27 @@
free($1);
}
+// For lldb::SBInputReader::Callback
+%typemap(in) (lldb::SBInputReader::Callback callback, void *callback_baton) {
+ if (!PyCallable_Check(reinterpret_cast<PyObject*>($input))) {
+ PyErr_SetString(PyExc_TypeError, "Need a callable object!");
+ return NULL;
+ }
+
+ // Don't lose the callback reference
+ Py_INCREF($input);
+ $1 = LLDBSwigPythonCallSBInputReaderCallback;
+ $2 = $input;
+}
+
+%typemap(typecheck) (lldb::SBInputReader::Callback callback, void *baton) {
+ if (!PyCallable_Check(reinterpret_cast<PyObject*>($input))) {
+ $1 = 0;
+ } else {
+ $1 = 1;
+ }
+}
+
%typemap(in) FILE * {
if ($input == Py_None)
$1 = NULL;
diff --git a/scripts/Python/python-wrapper.swig b/scripts/Python/python-wrapper.swig
index 73bad8d..9b48f3b 100644
--- a/scripts/Python/python-wrapper.swig
+++ b/scripts/Python/python-wrapper.swig
@@ -823,5 +823,61 @@
}
return retval;
}
+%}
+
+%runtime %{
+// Forward declaration to be inserted at the start of LLDBWrapPython.h
+// I used runtime as a hack to make SWIG place it where it's needed.
+// This is needed to use LLDBSwigPythonCallSBInputReaderCallback in the
+// typemaps and in the extensions (SBInputReader.__del__()).
+#include "SBInputReader.h"
+
+size_t
+LLDBSwigPythonCallSBInputReaderCallback(void *baton,
+ lldb::SBInputReader *reader,
+ lldb::InputReaderAction notification,
+ const char*bytes,
+ size_t bytes_len);
+%}
+
+%wrapper %{
+// For the InputReader Callback functions
+SWIGEXPORT size_t
+LLDBSwigPythonCallSBInputReaderCallback(void *baton,
+ lldb::SBInputReader *reader,
+ lldb::InputReaderAction notification,
+ const char*bytes,
+ size_t bytes_len) {
+ SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+
+ PyObject *py_InputReader = SWIG_NewPointerObj(reader, SWIGTYPE_p_lldb__SBInputReader, false);
+ PyObject *py_Notification = PyInt_FromLong(notification);
+ PyObject *py_Bytes = PyBytes_FromStringAndSize(bytes, bytes_len);
+
+ PyObject *tuple = PyTuple_Pack(3, py_InputReader, py_Notification, py_Bytes);
+ PyObject *res = PyObject_Call(reinterpret_cast<PyObject*>(baton), tuple, NULL);
+ Py_DECREF(tuple);
+ Py_DECREF(py_InputReader);
+ Py_DECREF(py_Notification);
+ Py_DECREF(py_Bytes);
+
+ if (res == NULL) {
+ PyObject *exc = PyErr_Occurred();
+ if (exc) {
+ ::puts("\nErroring out at LLDBSwigPythonCallSBInputReaderCallback");
+ PyErr_Print();
+ }
+ return 0;
+ }
+
+ size_t result = 0;
+ // If the callback misbehaves and returns Py_None, assume it returned 0
+ if (res != Py_None)
+ result = static_cast<size_t>(PyInt_AsSsize_t(res));
+
+ Py_DECREF(res);
+ SWIG_PYTHON_THREAD_END_BLOCK;
+ return result;
+}
%}