From: Filipe C. <fi...@gm...> - 2012-04-18 17:33:12
|
Hi all! I'm using a C++ library with Python bindings (lldb), and I'm having some trouble with callbacks. I implemented typemaps and a helper function, in order to be able to use a Python callable object as a callback in the C++ library. My problem is when Python code calls C++ code that then calls a Python callback. For reference, I have these type maps: ------------------------------------------------- // For SBDebugger::DispatchInput (the function that will call the callback function) %typemap(in) (const void *data, size_t data_len) { if (PyString_Check($input)) { $1 = static_cast<void *>(PyString_AsString($input)); $2 = PyString_Size($input); } else if(PyByteArray_Check($input)) { $1 = static_cast<void *>(PyByteArray_AsString($input)); $2 = PyByteArray_Size($input); } else { PyErr_SetString(PyExc_ValueError, "Expecting a string or byte array"); return NULL; } } // For lldb::SBInputReader::Callback lldb::SBInputReader::Callback LLDBSwigPythonCallSBInputReaderCallback; %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; } $1 = LLDBSwigPythonCallSBInputReaderCallback; $2 = $input; } %typemap(typecheck) (lldb::SBInputReader::Callback callback, void *baton) { if (!PyCallable_Check(reinterpret_cast<PyObject*>($input))) { $1 = 0; } else { $1 = 1; } } ------------------------------------------------- And this helper function: ------------------------------------------------- // For the InputReader Callback functions %{ size_t LLDBSwigPythonCallSBInputReaderCallback(void *baton, lldb::SBInputReader *reader, lldb::InputReaderAction notification, const char*bytes, size_t bytes_len) { SWIG_PYTHON_THREAD_BEGIN_BLOCK; PyErr_Clear(); PyObject *res = PyObject_CallFunction(reinterpret_cast<PyObject*>(baton), // s# converts to char * + Py_ssize_t const_cast<char*>("Ois#"), SWIG_NewPointerObj(reader, SWIGTYPE_p_lldb__SBInputReader, false), notification, bytes, bytes_len); PyObject *exc = PyErr_Occurred(); if (exc) { ::puts("Erroring out at LLDBSwigPythonCallSBInputReaderCallback\n"); return 0; } size_t result = static_cast<size_t>(PyInt_AsSsize_t(res)); SWIG_PYTHON_THREAD_END_BLOCK; return result; } %} ------------------------------------------------- I even tried adding an exception block, but that was a no-op (the cpp file generated by swig didn't change): ------------------------------------------------- %exception lldb::SBDebugger::DispatchInput(const void *data, size_t data_len) { $action if (PyErr_Occurred()) return NULL; } ------------------------------------------------- Am I doing anything wrong? What can I do to try and signal an error when returning from DispatchInput, if an error was signaled in the callback? Thanks in advance, Filipe |