cv2_util.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. #include "cv2_util.hpp"
  2. #include "opencv2/core.hpp"
  3. #include "opencv2/core/utils/configuration.private.hpp"
  4. #include "opencv2/core/utils/logger.hpp"
  5. PyObject* opencv_error = NULL;
  6. cv::TLSData<std::vector<std::string> > conversionErrorsTLS;
  7. using namespace cv;
  8. //======================================================================================================================
  9. bool isPythonBindingsDebugEnabled()
  10. {
  11. static bool param_debug = cv::utils::getConfigurationParameterBool("OPENCV_PYTHON_DEBUG", false);
  12. return param_debug;
  13. }
  14. void emit_failmsg(PyObject * exc, const char *msg)
  15. {
  16. static bool param_debug = isPythonBindingsDebugEnabled();
  17. if (param_debug)
  18. {
  19. CV_LOG_WARNING(NULL, "Bindings conversion failed: " << msg);
  20. }
  21. PyErr_SetString(exc, msg);
  22. }
  23. int failmsg(const char *fmt, ...)
  24. {
  25. char str[1000];
  26. va_list ap;
  27. va_start(ap, fmt);
  28. vsnprintf(str, sizeof(str), fmt, ap);
  29. va_end(ap);
  30. emit_failmsg(PyExc_TypeError, str);
  31. return 0;
  32. }
  33. PyObject* failmsgp(const char *fmt, ...)
  34. {
  35. char str[1000];
  36. va_list ap;
  37. va_start(ap, fmt);
  38. vsnprintf(str, sizeof(str), fmt, ap);
  39. va_end(ap);
  40. emit_failmsg(PyExc_TypeError, str);
  41. return 0;
  42. }
  43. void pyRaiseCVException(const cv::Exception &e)
  44. {
  45. PyObject_SetAttrString(opencv_error, "file", PyString_FromString(e.file.c_str()));
  46. PyObject_SetAttrString(opencv_error, "func", PyString_FromString(e.func.c_str()));
  47. PyObject_SetAttrString(opencv_error, "line", PyInt_FromLong(e.line));
  48. PyObject_SetAttrString(opencv_error, "code", PyInt_FromLong(e.code));
  49. PyObject_SetAttrString(opencv_error, "msg", PyString_FromString(e.msg.c_str()));
  50. PyObject_SetAttrString(opencv_error, "err", PyString_FromString(e.err.c_str()));
  51. PyErr_SetString(opencv_error, e.what());
  52. }
  53. //======================================================================================================================
  54. void pyRaiseCVOverloadException(const std::string& functionName)
  55. {
  56. const std::vector<std::string>& conversionErrors = conversionErrorsTLS.getRef();
  57. const std::size_t conversionErrorsCount = conversionErrors.size();
  58. if (conversionErrorsCount > 0)
  59. {
  60. // In modern std libraries small string optimization is used = no dynamic memory allocations,
  61. // but it can be applied only for string with length < 18 symbols (in GCC)
  62. const std::string bullet = "\n - ";
  63. // Estimate required buffer size - save dynamic memory allocations = faster
  64. std::size_t requiredBufferSize = bullet.size() * conversionErrorsCount;
  65. for (std::size_t i = 0; i < conversionErrorsCount; ++i)
  66. {
  67. requiredBufferSize += conversionErrors[i].size();
  68. }
  69. // Only string concatenation is required so std::string is way faster than
  70. // std::ostringstream
  71. std::string errorMessage("Overload resolution failed:");
  72. errorMessage.reserve(errorMessage.size() + requiredBufferSize);
  73. for (std::size_t i = 0; i < conversionErrorsCount; ++i)
  74. {
  75. errorMessage += bullet;
  76. errorMessage += conversionErrors[i];
  77. }
  78. cv::Exception exception(Error::StsBadArg, errorMessage, functionName, "", -1);
  79. pyRaiseCVException(exception);
  80. }
  81. else
  82. {
  83. cv::Exception exception(Error::StsInternal, "Overload resolution failed, but no errors reported",
  84. functionName, "", -1);
  85. pyRaiseCVException(exception);
  86. }
  87. }
  88. void pyPopulateArgumentConversionErrors()
  89. {
  90. if (PyErr_Occurred())
  91. {
  92. PySafeObject exception_type;
  93. PySafeObject exception_value;
  94. PySafeObject exception_traceback;
  95. PyErr_Fetch(exception_type, exception_value, exception_traceback);
  96. PyErr_NormalizeException(exception_type, exception_value,
  97. exception_traceback);
  98. PySafeObject exception_message(PyObject_Str(exception_value));
  99. std::string message;
  100. getUnicodeString(exception_message, message);
  101. #ifdef CV_CXX11
  102. conversionErrorsTLS.getRef().push_back(std::move(message));
  103. #else
  104. conversionErrorsTLS.getRef().push_back(message);
  105. #endif
  106. }
  107. }
  108. //======================================================================================================================
  109. static int OnError(int status, const char *func_name, const char *err_msg, const char *file_name, int line, void *userdata)
  110. {
  111. PyGILState_STATE gstate;
  112. gstate = PyGILState_Ensure();
  113. PyObject *on_error = (PyObject*)userdata;
  114. PyObject *args = Py_BuildValue("isssi", status, func_name, err_msg, file_name, line);
  115. PyObject *r = PyObject_Call(on_error, args, NULL);
  116. if (r == NULL) {
  117. PyErr_Print();
  118. } else {
  119. Py_DECREF(r);
  120. }
  121. Py_DECREF(args);
  122. PyGILState_Release(gstate);
  123. return 0; // The return value isn't used
  124. }
  125. PyObject *pycvRedirectError(PyObject*, PyObject *args, PyObject *kw)
  126. {
  127. const char *keywords[] = { "on_error", NULL };
  128. PyObject *on_error;
  129. if (!PyArg_ParseTupleAndKeywords(args, kw, "O", (char**)keywords, &on_error))
  130. return NULL;
  131. if ((on_error != Py_None) && !PyCallable_Check(on_error)) {
  132. PyErr_SetString(PyExc_TypeError, "on_error must be callable");
  133. return NULL;
  134. }
  135. // Keep track of the previous handler parameter, so we can decref it when no longer used
  136. static PyObject* last_on_error = NULL;
  137. if (last_on_error) {
  138. Py_DECREF(last_on_error);
  139. last_on_error = NULL;
  140. }
  141. if (on_error == Py_None) {
  142. ERRWRAP2(redirectError(NULL));
  143. } else {
  144. last_on_error = on_error;
  145. Py_INCREF(last_on_error);
  146. ERRWRAP2(redirectError(OnError, last_on_error));
  147. }
  148. Py_RETURN_NONE;
  149. }