From 6eb31e7391d27fc4a78122d45138e51eae9d6743 Mon Sep 17 00:00:00 2001 From: Filipe Cabecinhas Date: Wed, 22 Aug 2012 13:25:10 +0000 Subject: 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). llvm-svn: 162356 --- lldb/scripts/Python/python-extensions.swig | 11 +++++- lldb/scripts/Python/python-typemaps.swig | 21 +++++++++++ lldb/scripts/Python/python-wrapper.swig | 56 ++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 1 deletion(-) (limited to 'lldb/scripts/Python') diff --git a/lldb/scripts/Python/python-extensions.swig b/lldb/scripts/Python/python-extensions.swig index cd8f1cf..24f06a1 100644 --- a/lldb/scripts/Python/python-extensions.swig +++ b/lldb/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/lldb/scripts/Python/python-typemaps.swig b/lldb/scripts/Python/python-typemaps.swig index c269795..e212d3f 100644 --- a/lldb/scripts/Python/python-typemaps.swig +++ b/lldb/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($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($input))) { + $1 = 0; + } else { + $1 = 1; + } +} + %typemap(in) FILE * { if ($input == Py_None) $1 = NULL; diff --git a/lldb/scripts/Python/python-wrapper.swig b/lldb/scripts/Python/python-wrapper.swig index 73bad8d..9b48f3b 100644 --- a/lldb/scripts/Python/python-wrapper.swig +++ b/lldb/scripts/Python/python-wrapper.swig @@ -823,5 +823,61 @@ LLDBSwigPythonCallModuleInit } 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(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(PyInt_AsSsize_t(res)); + + Py_DECREF(res); + SWIG_PYTHON_THREAD_END_BLOCK; + return result; +} %} -- cgit v1.1