From 298ccf64879591010dac0a71aed25dc469356d04 Mon Sep 17 00:00:00 2001 From: Andrey Kamaev Date: Fri, 12 Apr 2013 22:35:46 +0400 Subject: [PATCH] Turn pyopencv_to and pyopencv_from into templates This protects from unwanted implicit conversions between types at compile time. --- modules/python/src2/cv2.cpp | 169 +++++++++++++++++++++++++----------- modules/python/src2/gen2.py | 10 +-- 2 files changed, 121 insertions(+), 58 deletions(-) diff --git a/modules/python/src2/cv2.cpp b/modules/python/src2/cv2.cpp index c75ce0ffa8..af015eb8da 100644 --- a/modules/python/src2/cv2.cpp +++ b/modules/python/src2/cv2.cpp @@ -214,11 +214,19 @@ public: NumpyAllocator g_numpyAllocator; + +template static +bool pyopencv_to(PyObject* obj, T& p, const char* name = ""); + +template static +PyObject* pyopencv_from(const T& src); + enum { ARG_NONE = 0, ARG_MAT = 1, ARG_SCALAR = 2 }; // special case, when the convertor needs full ArgInfo structure -static int pyopencv_to(const PyObject* o, Mat& m, const ArgInfo info, bool allowND=true) +static bool pyopencv_to(PyObject* o, Mat& m, const ArgInfo info) { + bool allowND = true; if(!o || o == Py_None) { if( !m.data ) @@ -378,7 +386,8 @@ static int pyopencv_to(const PyObject* o, Mat& m, const ArgInfo info, bool allow return true; } -static PyObject* pyopencv_from(const Mat& m) +template<> +PyObject* pyopencv_from(const Mat& m) { if( !m.data ) Py_RETURN_NONE; @@ -393,7 +402,8 @@ static PyObject* pyopencv_from(const Mat& m) return pyObjectFromRefcount(p->refcount); } -static bool pyopencv_to(PyObject *o, Scalar& s, const char *name = "") +template<> +bool pyopencv_to(PyObject *o, Scalar& s, const char *name) { if(!o || o == Py_None) return true; @@ -427,17 +437,20 @@ static bool pyopencv_to(PyObject *o, Scalar& s, const char *name = "") return true; } -static inline PyObject* pyopencv_from(const Scalar& src) +template<> +PyObject* pyopencv_from(const Scalar& src) { return Py_BuildValue("(dddd)", src[0], src[1], src[2], src[3]); } -static PyObject* pyopencv_from(bool value) +template<> +PyObject* pyopencv_from(const bool& value) { return PyBool_FromLong(value); } -static bool pyopencv_to(PyObject* obj, bool& value, const char* name = "") +template<> +bool pyopencv_to(PyObject* obj, bool& value, const char* name) { (void)name; if(!obj || obj == Py_None) @@ -449,12 +462,14 @@ static bool pyopencv_to(PyObject* obj, bool& value, const char* name = " +PyObject* pyopencv_from(const size_t& value) { return PyLong_FromSize_t(value); } -static bool pyopencv_to(PyObject* obj, size_t& value, const char* name = "") +template<> +bool pyopencv_to(PyObject* obj, size_t& value, const char* name) { (void)name; if(!obj || obj == Py_None) @@ -463,22 +478,33 @@ static bool pyopencv_to(PyObject* obj, size_t& value, const char* name = " +PyObject* pyopencv_from(const int& value) { return PyInt_FromLong(value); } -static PyObject* pyopencv_from(cvflann_flann_algorithm_t value) +template<> +PyObject* pyopencv_from(const cvflann_flann_algorithm_t& value) { return PyInt_FromLong(int(value)); } -static PyObject* pyopencv_from(cvflann_flann_distance_t value) +template<> +PyObject* pyopencv_from(const cvflann_flann_distance_t& value) { return PyInt_FromLong(int(value)); } -static bool pyopencv_to(PyObject* obj, int& value, const char* name = "") +template<> +bool pyopencv_to(PyObject*, cv::flann::SearchParams &, const char *) +{ + CV_Assert(!"not implemented"); + return false; +} + +template<> +bool pyopencv_to(PyObject* obj, int& value, const char* name) { (void)name; if(!obj || obj == Py_None) @@ -492,12 +518,14 @@ static bool pyopencv_to(PyObject* obj, int& value, const char* name = " return value != -1 || !PyErr_Occurred(); } -static PyObject* pyopencv_from(uchar value) +template<> +PyObject* pyopencv_from(const uchar& value) { return PyInt_FromLong(value); } -static bool pyopencv_to(PyObject* obj, uchar& value, const char* name = "") +template<> +bool pyopencv_to(PyObject* obj, uchar& value, const char* name) { (void)name; if(!obj || obj == Py_None) @@ -507,12 +535,14 @@ static bool pyopencv_to(PyObject* obj, uchar& value, const char* name = " +PyObject* pyopencv_from(const double& value) { return PyFloat_FromDouble(value); } -static bool pyopencv_to(PyObject* obj, double& value, const char* name = "") +template<> +bool pyopencv_to(PyObject* obj, double& value, const char* name) { (void)name; if(!obj || obj == Py_None) @@ -524,12 +554,14 @@ static bool pyopencv_to(PyObject* obj, double& value, const char* name = " +PyObject* pyopencv_from(const float& value) { return PyFloat_FromDouble(value); } -static bool pyopencv_to(PyObject* obj, float& value, const char* name = "") +template<> +bool pyopencv_to(PyObject* obj, float& value, const char* name) { (void)name; if(!obj || obj == Py_None) @@ -541,17 +573,20 @@ static bool pyopencv_to(PyObject* obj, float& value, const char* name = " +PyObject* pyopencv_from(const int64& value) { return PyLong_FromLongLong(value); } -static PyObject* pyopencv_from(const String& value) +template<> +PyObject* pyopencv_from(const String& value) { return PyString_FromString(value.empty() ? "" : value.c_str()); } -static bool pyopencv_to(PyObject* obj, String& value, const char* name = "") +template<> +bool pyopencv_to(PyObject* obj, String& value, const char* name) { (void)name; if(!obj || obj == Py_None) @@ -563,7 +598,8 @@ static bool pyopencv_to(PyObject* obj, String& value, const char* name = " +bool pyopencv_to(PyObject* obj, Size& sz, const char* name) { (void)name; if(!obj || obj == Py_None) @@ -571,12 +607,14 @@ static inline bool pyopencv_to(PyObject* obj, Size& sz, const char* name = " 0; } -static inline PyObject* pyopencv_from(const Size& sz) +template<> +PyObject* pyopencv_from(const Size& sz) { return Py_BuildValue("(ii)", sz.width, sz.height); } -static inline bool pyopencv_to(PyObject* obj, Rect& r, const char* name = "") +template<> +bool pyopencv_to(PyObject* obj, Rect& r, const char* name) { (void)name; if(!obj || obj == Py_None) @@ -584,12 +622,14 @@ static inline bool pyopencv_to(PyObject* obj, Rect& r, const char* name = " 0; } -static inline PyObject* pyopencv_from(const Rect& r) +template<> +PyObject* pyopencv_from(const Rect& r) { return Py_BuildValue("(iiii)", r.x, r.y, r.width, r.height); } -static inline bool pyopencv_to(PyObject* obj, Range& r, const char* name = "") +template<> +bool pyopencv_to(PyObject* obj, Range& r, const char* name) { (void)name; if(!obj || obj == Py_None) @@ -602,12 +642,14 @@ static inline bool pyopencv_to(PyObject* obj, Range& r, const char* name = " 0; } -static inline PyObject* pyopencv_from(const Range& r) +template<> +PyObject* pyopencv_from(const Range& r) { return Py_BuildValue("(ii)", r.start, r.end); } -static inline bool pyopencv_to(PyObject* obj, Point& p, const char* name = "") +template<> +bool pyopencv_to(PyObject* obj, Point& p, const char* name) { (void)name; if(!obj || obj == Py_None) @@ -622,7 +664,8 @@ static inline bool pyopencv_to(PyObject* obj, Point& p, const char* name = " 0; } -static inline bool pyopencv_to(PyObject* obj, Point2f& p, const char* name = "") +template<> +bool pyopencv_to(PyObject* obj, Point2f& p, const char* name) { (void)name; if(!obj || obj == Py_None) @@ -637,17 +680,20 @@ static inline bool pyopencv_to(PyObject* obj, Point2f& p, const char* name = " 0; } -static inline PyObject* pyopencv_from(const Point& p) +template<> +PyObject* pyopencv_from(const Point& p) { return Py_BuildValue("(ii)", p.x, p.y); } -static inline PyObject* pyopencv_from(const Point2f& p) +template<> +PyObject* pyopencv_from(const Point2f& p) { return Py_BuildValue("(dd)", p.x, p.y); } -static inline bool pyopencv_to(PyObject* obj, Vec3d& v, const char* name = "") +template<> +bool pyopencv_to(PyObject* obj, Vec3d& v, const char* name) { (void)name; if(!obj) @@ -655,17 +701,20 @@ static inline bool pyopencv_to(PyObject* obj, Vec3d& v, const char* name = " 0; } -static inline PyObject* pyopencv_from(const Vec3d& v) +template<> +PyObject* pyopencv_from(const Vec3d& v) { return Py_BuildValue("(ddd)", v[0], v[1], v[2]); } -static inline PyObject* pyopencv_from(const Vec2d& v) +template<> +PyObject* pyopencv_from(const Vec2d& v) { return Py_BuildValue("(dd)", v[0], v[1]); } -static inline PyObject* pyopencv_from(const Point2d& p) +template<> +PyObject* pyopencv_from(const Point2d& p) { return Py_BuildValue("(dd)", p.x, p.y); } @@ -779,20 +828,18 @@ template struct pyopencvVecConverter } }; - -template static inline bool pyopencv_to(PyObject* obj, std::vector<_Tp>& value, const ArgInfo info) +template +bool pyopencv_to(PyObject* obj, std::vector<_Tp>& value, const ArgInfo info) { return pyopencvVecConverter<_Tp>::to(obj, value, info); } -template static inline PyObject* pyopencv_from(const std::vector<_Tp>& value) +template +PyObject* pyopencv_from(const std::vector<_Tp>& value) { return pyopencvVecConverter<_Tp>::from(value); } -static PyObject* pyopencv_from(const KeyPoint&); -static PyObject* pyopencv_from(const DMatch&); - template static inline bool pyopencv_to_generic_vec(PyObject* obj, std::vector<_Tp>& value, const ArgInfo info) { if(!obj || obj == Py_None) @@ -902,7 +949,8 @@ template<> struct pyopencvVecConverter } }; -static inline bool pyopencv_to(PyObject *obj, TermCriteria& dst, const char *name="") +template<> +bool pyopencv_to(PyObject *obj, TermCriteria& dst, const char *name) { (void)name; if(!obj) @@ -910,12 +958,14 @@ static inline bool pyopencv_to(PyObject *obj, TermCriteria& dst, const char *nam return PyArg_ParseTuple(obj, "iid", &dst.type, &dst.maxCount, &dst.epsilon) > 0; } -static inline PyObject* pyopencv_from(const TermCriteria& src) +template<> +PyObject* pyopencv_from(const TermCriteria& src) { return Py_BuildValue("(iid)", src.type, src.maxCount, src.epsilon); } -static inline bool pyopencv_to(PyObject *obj, RotatedRect& dst, const char *name="") +template<> +bool pyopencv_to(PyObject *obj, RotatedRect& dst, const char *name) { (void)name; if(!obj) @@ -923,12 +973,14 @@ static inline bool pyopencv_to(PyObject *obj, RotatedRect& dst, const char *name return PyArg_ParseTuple(obj, "(ff)(ff)f", &dst.center.x, &dst.center.y, &dst.size.width, &dst.size.height, &dst.angle) > 0; } -static inline PyObject* pyopencv_from(const RotatedRect& src) +template<> +PyObject* pyopencv_from(const RotatedRect& src) { return Py_BuildValue("((ff)(ff)f)", src.center.x, src.center.y, src.size.width, src.size.height, src.angle); } -static inline PyObject* pyopencv_from(const Moments& m) +template<> +PyObject* pyopencv_from(const Moments& m) { return Py_BuildValue("{s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d}", "m00", m.m00, "m10", m.m10, "m01", m.m01, @@ -940,7 +992,8 @@ static inline PyObject* pyopencv_from(const Moments& m) "nu30", m.nu30, "nu21", m.nu21, "nu12", m.nu12, "nu03", m.nu03); } -static bool pyopencv_to(PyObject *o, cv::flann::IndexParams& p, const char *name="") +template<> +bool pyopencv_to(PyObject *o, cv::flann::IndexParams& p, const char *name) { (void)name; bool ok = false; @@ -988,15 +1041,15 @@ static bool pyopencv_to(PyObject *o, cv::flann::IndexParams& p, const char *name return ok; } -template -static bool pyopencv_to(PyObject *o, Ptr& p, const char *name="") +template +bool pyopencv_to(PyObject *o, Ptr& p, const char *name) { p = new T(); return pyopencv_to(o, *p, name); } - -static bool pyopencv_to(PyObject *o, cvflann::flann_distance_t& dist, const char *name="") +template<> +bool pyopencv_to(PyObject *o, cvflann::flann_distance_t& dist, const char *name) { int d = (int)dist; bool ok = pyopencv_to(o, d, name); @@ -1008,7 +1061,8 @@ static bool pyopencv_to(PyObject *o, cvflann::flann_distance_t& dist, const char //////////////////////////////////////////////////////////////////////////////////////////////////// // TODO: REMOVE used only by ml wrapper -static bool pyopencv_to(PyObject *obj, CvTermCriteria& dst, const char *name="") +template<> +bool pyopencv_to(PyObject *obj, CvTermCriteria& dst, const char *name) { (void)name; if(!obj) @@ -1016,7 +1070,8 @@ static bool pyopencv_to(PyObject *obj, CvTermCriteria& dst, const char *name=" 0; } -static bool pyopencv_to(PyObject* obj, CvSlice& r, const char* name = "") +template<> +bool pyopencv_to(PyObject* obj, CvSlice& r, const char* name) { (void)name; if(!obj || obj == Py_None) @@ -1029,6 +1084,14 @@ static bool pyopencv_to(PyObject* obj, CvSlice& r, const char* name = " return PyArg_ParseTuple(obj, "ii", &r.start_index, &r.end_index) > 0; } +template<> +PyObject* pyopencv_from(CvDTreeNode* const & node) +{ + double value = node->value; + int ivalue = cvRound(value); + return value == ivalue ? PyInt_FromLong(ivalue) : PyFloat_FromDouble(value); +} + //////////////////////////////////////////////////////////////////////////////////////////////////// static void OnMouse(int event, int x, int y, int flags, void* param) diff --git a/modules/python/src2/gen2.py b/modules/python/src2/gen2.py index 8b060a7a85..0fed1838b0 100755 --- a/modules/python/src2/gen2.py +++ b/modules/python/src2/gen2.py @@ -53,14 +53,14 @@ static void pyopencv_${name}_dealloc(PyObject* self) PyObject_Del(self); } -static PyObject* pyopencv_from(const ${cname}& r) +template<> PyObject* pyopencv_from(const ${cname}& r) { pyopencv_${name}_t *m = PyObject_NEW(pyopencv_${name}_t, &pyopencv_${name}_Type); m->v = r; return (PyObject*)m; } -static bool pyopencv_to(PyObject* src, ${cname}& dst, const char* name="") +template<> bool pyopencv_to(PyObject* src, ${cname}& dst, const char* name) { if( src == NULL || src == Py_None ) return true; @@ -96,7 +96,7 @@ static void pyopencv_${name}_dealloc(PyObject* self) PyObject_Del(self); } -static PyObject* pyopencv_from(const Ptr<${cname}>& r) +template<> PyObject* pyopencv_from(const Ptr<${cname}>& r) { pyopencv_${name}_t *m = PyObject_NEW(pyopencv_${name}_t, &pyopencv_${name}_Type); new (&(m->v)) Ptr<$cname1>(); // init Ptr with placement new @@ -104,7 +104,7 @@ static PyObject* pyopencv_from(const Ptr<${cname}>& r) return (PyObject*)m; } -static bool pyopencv_to(PyObject* src, Ptr<${cname}>& dst, const char* name="") +template<> bool pyopencv_to(PyObject* src, Ptr<${cname}>& dst, const char* name) { if( src == NULL || src == Py_None ) return true; @@ -120,7 +120,7 @@ static bool pyopencv_to(PyObject* src, Ptr<${cname}>& dst, const char* name=" bool pyopencv_to(PyObject* src, ${cname}& dst, const char* name); """) gen_template_set_prop_from_map = Template("""