Commit 8c1d8ecc authored by Dan Mašek's avatar Dan Mašek Committed by Alexander Alekhin

Merge pull request #11207 from dan-masek:add_redirect_error

* Add Python support for error message handlers.

* Move the static variable to the only function that uses it.

* Remove the optional param (user data), since this can already be handled by closures.

* Correct the help string.

* python: added redirectError test
parent f95e91e2
......@@ -1536,6 +1536,57 @@ PyObject* pyopencv_from(const Moments& m)
#include "pyopencv_custom_headers.h"
static int OnError(int status, const char *func_name, const char *err_msg, const char *file_name, int line, void *userdata)
{
PyGILState_STATE gstate;
gstate = PyGILState_Ensure();
PyObject *on_error = (PyObject*)userdata;
PyObject *args = Py_BuildValue("isssi", status, func_name, err_msg, file_name, line);
PyObject *r = PyObject_Call(on_error, args, NULL);
if (r == NULL) {
PyErr_Print();
} else {
Py_DECREF(r);
}
Py_DECREF(args);
PyGILState_Release(gstate);
return 0; // The return value isn't used
}
static PyObject *pycvRedirectError(PyObject*, PyObject *args, PyObject *kw)
{
const char *keywords[] = { "on_error", NULL };
PyObject *on_error;
if (!PyArg_ParseTupleAndKeywords(args, kw, "O", (char**)keywords, &on_error))
return NULL;
if ((on_error != Py_None) && !PyCallable_Check(on_error)) {
PyErr_SetString(PyExc_TypeError, "on_error must be callable");
return NULL;
}
// Keep track of the previous handler parameter, so we can decref it when no longer used
static PyObject* last_on_error = NULL;
if (last_on_error) {
Py_DECREF(last_on_error);
last_on_error = NULL;
}
if (on_error == Py_None) {
ERRWRAP2(redirectError(NULL));
} else {
last_on_error = on_error;
Py_INCREF(last_on_error);
ERRWRAP2(redirectError(OnError, last_on_error));
}
Py_RETURN_NONE;
}
static void OnMouse(int event, int x, int y, int flags, void* param)
{
PyGILState_STATE gstate;
......@@ -1683,6 +1734,7 @@ static int convert_to_char(PyObject *o, char *dst, const char *name = "no_name")
#include "pyopencv_generated_funcs.h"
static PyMethodDef special_methods[] = {
{"redirectError", (PyCFunction)pycvRedirectError, METH_VARARGS | METH_KEYWORDS, "redirectError(onError) -> None"},
#ifdef HAVE_OPENCV_HIGHGUI
{"createTrackbar", pycvCreateTrackbar, METH_VARARGS, "createTrackbar(trackbarName, windowName, value, count, onChange) -> None"},
{"createButton", (PyCFunction)pycvCreateButton, METH_VARARGS | METH_KEYWORDS, "createButton(buttonName, onChange [, userData, buttonType, initialButtonState]) -> None"},
......
......@@ -18,5 +18,33 @@ class Bindings(NewOpenCVTests):
boost.getMaxDepth() # from ml::DTrees
boost.isClassifier() # from ml::StatModel
def test_redirectError(self):
try:
cv.imshow("", None) # This causes an assert
self.assertEqual("Dead code", 0)
except cv.error as e:
pass
handler_called = [False]
def test_error_handler(status, func_name, err_msg, file_name, line):
handler_called[0] = True
cv.redirectError(test_error_handler)
try:
cv.imshow("", None) # This causes an assert
self.assertEqual("Dead code", 0)
except cv.error as e:
self.assertEqual(handler_called[0], True)
pass
cv.redirectError(None)
try:
cv.imshow("", None) # This causes an assert
self.assertEqual("Dead code", 0)
except cv.error as e:
pass
if __name__ == '__main__':
NewOpenCVTests.bootstrap()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment