Commit ab8de8f5 authored by Vitaliy Lyudvichenko's avatar Vitaliy Lyudvichenko

Adding of user-defined type conversions for python bindings inside module directories

Adding of destructor and placement new constructors for classes wrapped with CV_EXPORTS_W_SIMPLE macro
parent 35d0a45d
......@@ -142,5 +142,6 @@ public:
So these are the major extension macros available in OpenCV. Typically, a developer has to put
proper macros in their appropriate positions. Rest is done by generator scripts. Sometimes, there
may be an exceptional cases where generator scripts cannot create the wrappers. Such functions need
to be handled manually. But most of the time, a code written according to OpenCV coding guidelines
will be automatically wrapped by generator scripts.
to be handled manually, to do this write your own pyopencv_*.hpp extending headers and put them into
misc/python subdirectory of your module. But most of the time, a code written according to OpenCV
coding guidelines will be automatically wrapped by generator scripts.
\ No newline at end of file
#ifdef HAVE_OPENCV_FEATURES2D
typedef SimpleBlobDetector::Params SimpleBlobDetector_Params;
#endif
\ No newline at end of file
#ifdef HAVE_OPENCV_FLANN
typedef cvflann::flann_distance_t cvflann_flann_distance_t;
typedef cvflann::flann_algorithm_t cvflann_flann_algorithm_t;
template<>
PyObject* pyopencv_from(const cvflann_flann_algorithm_t& value)
{
return PyInt_FromLong(int(value));
}
template<>
PyObject* pyopencv_from(const cvflann_flann_distance_t& value)
{
return PyInt_FromLong(int(value));
}
template<>
bool pyopencv_to(PyObject *o, cv::flann::IndexParams& p, const char *name)
{
(void)name;
bool ok = true;
PyObject* key = NULL;
PyObject* item = NULL;
Py_ssize_t pos = 0;
if(PyDict_Check(o)) {
while(PyDict_Next(o, &pos, &key, &item)) {
if( !PyString_Check(key) ) {
ok = false;
break;
}
String k = PyString_AsString(key);
if( PyString_Check(item) )
{
const char* value = PyString_AsString(item);
p.setString(k, value);
}
else if( !!PyBool_Check(item) )
p.setBool(k, item == Py_True);
else if( PyInt_Check(item) )
{
int value = (int)PyInt_AsLong(item);
if( strcmp(k.c_str(), "algorithm") == 0 )
p.setAlgorithm(value);
else
p.setInt(k, value);
}
else if( PyFloat_Check(item) )
{
double value = PyFloat_AsDouble(item);
p.setDouble(k, value);
}
else
{
ok = false;
break;
}
}
}
return ok && !PyErr_Occurred();
}
template<>
bool pyopencv_to(PyObject* obj, cv::flann::SearchParams & value, const char * name)
{
return pyopencv_to<cv::flann::IndexParams>(obj, value, 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);
dist = (cvflann::flann_distance_t)d;
return ok;
}
#endif
\ No newline at end of file
template<>
bool pyopencv_to(PyObject *obj, CvTermCriteria& dst, const char *name)
{
(void)name;
if(!obj)
return true;
return PyArg_ParseTuple(obj, "iid", &dst.type, &dst.max_iter, &dst.epsilon) > 0;
}
template<>
bool pyopencv_to(PyObject* obj, CvSlice& r, const char* name)
{
(void)name;
if(!obj || obj == Py_None)
return true;
if(PyObject_Size(obj) == 0)
{
r = CV_WHOLE_SEQ;
return true;
}
return PyArg_ParseTuple(obj, "ii", &r.start_index, &r.end_index) > 0;
}
\ No newline at end of file
......@@ -24,8 +24,11 @@ foreach(m ${OPENCV_MODULES_BUILD})
endforeach()
set(opencv_hdrs "")
set(opencv_userdef_hdrs "")
foreach(m ${OPENCV_PYTHON_MODULES})
list(APPEND opencv_hdrs ${OPENCV_MODULE_${m}_HEADERS})
file(GLOB userdef_hdrs ${OPENCV_MODULE_${m}_LOCATION}/misc/python/pyopencv*.hpp)
list(APPEND opencv_userdef_hdrs ${userdef_hdrs})
endforeach(m)
# header blacklist
......@@ -52,7 +55,13 @@ add_custom_command(
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/headers.txt
DEPENDS ${opencv_hdrs})
ocv_add_library(${the_module} MODULE ${PYTHON_SOURCE_DIR}/src2/cv2.cpp ${cv2_generated_hdrs})
set(cv2_custom_hdr "${CMAKE_CURRENT_BINARY_DIR}/pyopencv_custom_headers.h")
file(WRITE ${cv2_custom_hdr} "//user-defined headers\n")
foreach(uh ${opencv_userdef_hdrs})
file(APPEND ${cv2_custom_hdr} "#include \"${uh}\"\n")
endforeach(uh)
ocv_add_library(${the_module} MODULE ${PYTHON_SOURCE_DIR}/src2/cv2.cpp ${cv2_generated_hdrs} ${opencv_userdef_hdrs} ${cv2_custom_hdr})
if(APPLE)
set_target_properties(${the_module} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")
......
......@@ -111,19 +111,6 @@ typedef std::vector<std::vector<Point2f> > vector_vector_Point2f;
typedef std::vector<std::vector<Point3f> > vector_vector_Point3f;
typedef std::vector<std::vector<DMatch> > vector_vector_DMatch;
#ifdef HAVE_OPENCV_FEATURES2D
typedef SimpleBlobDetector::Params SimpleBlobDetector_Params;
#endif
#ifdef HAVE_OPENCV_FLANN
typedef cvflann::flann_distance_t cvflann_flann_distance_t;
typedef cvflann::flann_algorithm_t cvflann_flann_algorithm_t;
#endif
#ifdef HAVE_OPENCV_STITCHING
typedef Stitcher::Status Status;
#endif
static PyObject* failmsgp(const char *fmt, ...)
{
char str[1000];
......@@ -469,14 +456,6 @@ PyObject* pyopencv_from(const bool& value)
return PyBool_FromLong(value);
}
#ifdef HAVE_OPENCV_STITCHING
template<>
PyObject* pyopencv_from(const Status& value)
{
return PyInt_FromLong(value);
}
#endif
template<>
bool pyopencv_to(PyObject* obj, bool& value, const char* name)
{
......@@ -512,20 +491,6 @@ PyObject* pyopencv_from(const int& value)
return PyInt_FromLong(value);
}
#ifdef HAVE_OPENCV_FLANN
template<>
PyObject* pyopencv_from(const cvflann_flann_algorithm_t& value)
{
return PyInt_FromLong(int(value));
}
template<>
PyObject* pyopencv_from(const cvflann_flann_distance_t& value)
{
return PyInt_FromLong(int(value));
}
#endif
template<>
bool pyopencv_to(PyObject* obj, int& value, const char* name)
{
......@@ -1094,62 +1059,6 @@ PyObject* pyopencv_from(const Moments& m)
"nu30", m.nu30, "nu21", m.nu21, "nu12", m.nu12, "nu03", m.nu03);
}
#ifdef HAVE_OPENCV_FLANN
template<>
bool pyopencv_to(PyObject *o, cv::flann::IndexParams& p, const char *name)
{
(void)name;
bool ok = true;
PyObject* key = NULL;
PyObject* item = NULL;
Py_ssize_t pos = 0;
if(PyDict_Check(o)) {
while(PyDict_Next(o, &pos, &key, &item)) {
if( !PyString_Check(key) ) {
ok = false;
break;
}
String k = PyString_AsString(key);
if( PyString_Check(item) )
{
const char* value = PyString_AsString(item);
p.setString(k, value);
}
else if( !!PyBool_Check(item) )
p.setBool(k, item == Py_True);
else if( PyInt_Check(item) )
{
int value = (int)PyInt_AsLong(item);
if( strcmp(k.c_str(), "algorithm") == 0 )
p.setAlgorithm(value);
else
p.setInt(k, value);
}
else if( PyFloat_Check(item) )
{
double value = PyFloat_AsDouble(item);
p.setDouble(k, value);
}
else
{
ok = false;
break;
}
}
}
return ok && !PyErr_Occurred();
}
template<>
bool pyopencv_to(PyObject* obj, cv::flann::SearchParams & value, const char * name)
{
return pyopencv_to<cv::flann::IndexParams>(obj, value, name);
}
#endif
template <typename T>
bool pyopencv_to(PyObject *o, Ptr<T>& p, const char *name)
{
......@@ -1157,45 +1066,7 @@ bool pyopencv_to(PyObject *o, Ptr<T>& p, const char *name)
return pyopencv_to(o, *p, name);
}
#ifdef HAVE_OPENCV_FLANN
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);
dist = (cvflann::flann_distance_t)d;
return ok;
}
#endif
////////////////////////////////////////////////////////////////////////////////////////////////////
// TODO: REMOVE used only by ml wrapper
template<>
bool pyopencv_to(PyObject *obj, CvTermCriteria& dst, const char *name)
{
(void)name;
if(!obj)
return true;
return PyArg_ParseTuple(obj, "iid", &dst.type, &dst.max_iter, &dst.epsilon) > 0;
}
template<>
bool pyopencv_to(PyObject* obj, CvSlice& r, const char* name)
{
(void)name;
if(!obj || obj == Py_None)
return true;
if(PyObject_Size(obj) == 0)
{
r = CV_WHOLE_SEQ;
return true;
}
return PyArg_ParseTuple(obj, "ii", &r.start_index, &r.end_index) > 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
#include "pyopencv_custom_headers.h"
static void OnMouse(int event, int x, int y, int flags, void* param)
{
......
......@@ -30,7 +30,7 @@ gen_template_call_constructor = Template("""self->v.reset(new ${cname}${args})""
gen_template_simple_call_constructor_prelude = Template("""self = PyObject_NEW(pyopencv_${name}_t, &pyopencv_${name}_Type);
if(self) """)
gen_template_simple_call_constructor = Template("""self->v = ${cname}${args}""")
gen_template_simple_call_constructor = Template("""new (&(self->v)) ${cname}${args}""")
gen_template_parse_args = Template("""const char* keywords[] = { $kw_list, NULL };
if( PyArg_ParseTupleAndKeywords(args, kw, "$fmtspec", (char**)keywords, $parse_arglist)$code_cvt )""")
......@@ -74,13 +74,14 @@ static PyTypeObject pyopencv_${name}_Type =
static void pyopencv_${name}_dealloc(PyObject* self)
{
((pyopencv_${name}_t*)self)->v.${cname}::~${sname}();
PyObject_Del(self);
}
template<> PyObject* pyopencv_from(const ${cname}& r)
{
pyopencv_${name}_t *m = PyObject_NEW(pyopencv_${name}_t, &pyopencv_${name}_Type);
m->v = r;
new (&m->v) ${cname}(r); //Copy constructor
return (PyObject*)m;
}
......@@ -258,6 +259,7 @@ class ClassInfo(object):
def __init__(self, name, decl=None):
self.cname = name.replace(".", "::")
self.name = self.wname = normalize_class_name(name)
self.sname = name[name.rfind('.') + 1:]
self.ismap = False
self.issimple = False
self.isalgorithm = False
......@@ -904,7 +906,7 @@ class PythonWrapperGenerator(object):
templ = gen_template_simple_type_decl
else:
templ = gen_template_type_decl
self.code_types.write(templ.substitute(name=name, wname=classinfo.wname, cname=classinfo.cname,
self.code_types.write(templ.substitute(name=name, wname=classinfo.wname, cname=classinfo.cname, sname=classinfo.sname,
cname1=("cv::Algorithm" if classinfo.isalgorithm else classinfo.cname)))
# register classes in the same order as they have been declared.
......
#ifdef HAVE_OPENCV_STITCHING
typedef Stitcher::Status Status;
template<>
PyObject* pyopencv_from(const Status& value)
{
return PyInt_FromLong(value);
}
#endif
\ No newline at end of file
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