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
This commit is contained in:
Filipe Cabecinhas 2012-08-22 13:25:10 +00:00
parent de17f86655
commit 6eb31e7391
4 changed files with 92 additions and 3 deletions

View File

@ -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):

View File

@ -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;

View File

@ -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<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;
}
%}

View File

@ -6,7 +6,10 @@ import sys
import lldb
def fuzz_obj(obj):
obj.Initialize(lldb.SBDebugger.Create(), None, None, 0, "$", "^", True)
try:
obj.Initialize(lldb.SBDebugger.Create(), None, 0, "$", "^", True)
except Exception:
pass
obj.IsActive()
obj.IsDone()
obj.SetIsDone(True)