Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
O
opencv
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
opencv
Commits
1caca211
Commit
1caca211
authored
Sep 05, 2017
by
Lewis B
Committed by
Alexander Alekhin
Sep 05, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Merge pull request #8934 from lewisjb:python-classes
* Refactor Python Classes
parent
42fbbfec
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
80 additions
and
30 deletions
+80
-30
cv2.cpp
modules/python/src2/cv2.cpp
+11
-5
gen2.py
modules/python/src2/gen2.py
+69
-25
No files found.
modules/python/src2/cv2.cpp
View file @
1caca211
...
@@ -1609,14 +1609,20 @@ void initcv2()
...
@@ -1609,14 +1609,20 @@ void initcv2()
return
;
return
;
#endif
#endif
#if PY_MAJOR_VERSION >= 3
#if PY_MAJOR_VERSION >= 3
Py_INCREF
(
&
cv2_UMatWrapperType
);
#define PUBLISH_OBJECT(name, type) Py_INCREF(&type);\
PyModule_AddObject(m, name, (PyObject *)&type);
#else
#else
// Unrolled Py_INCREF(&cv2_UMatWrapperType) without (PyObject*) cast
// Unrolled Py_INCREF(&type) without (PyObject*) cast
// due to "warning: dereferencing type-punned pointer will break strict-aliasing rules"
// due to "warning: dereferencing type-punned pointer will break strict-aliasing rules"
_Py_INC_REFTOTAL
_Py_REF_DEBUG_COMMA
(
&
cv2_UMatWrapperType
)
->
ob_refcnt
++
;
#define PUBLISH_OBJECT(name, type) _Py_INC_REFTOTAL _Py_REF_DEBUG_COMMA (&type)->ob_refcnt++;\
PyModule_AddObject(m, name, (PyObject *)&type);
#endif
#endif
PyModule_AddObject
(
m
,
"UMat"
,
(
PyObject
*
)
&
cv2_UMatWrapperType
);
PUBLISH_OBJECT
(
"UMat"
,
cv2_UMatWrapperType
);
#include "pyopencv_generated_type_publish.h"
#define PUBLISH(I) PyDict_SetItemString(d, #I, PyInt_FromLong(I))
#define PUBLISH(I) PyDict_SetItemString(d, #I, PyInt_FromLong(I))
//#define PUBLISHU(I) PyDict_SetItemString(d, #I, PyLong_FromUnsignedLong(I))
//#define PUBLISHU(I) PyDict_SetItemString(d, #I, PyLong_FromUnsignedLong(I))
...
...
modules/python/src2/gen2.py
View file @
1caca211
...
@@ -25,14 +25,12 @@ gen_template_check_self_algo = Template(""" $cname* _self_ = NULL;
...
@@ -25,14 +25,12 @@ gen_template_check_self_algo = Template(""" $cname* _self_ = NULL;
return failmsgp("Incorrect type of self (must be '${name}' or its derivative)");
return failmsgp("Incorrect type of self (must be '${name}' or its derivative)");
"""
)
"""
)
gen_template_call_constructor_prelude
=
Template
(
"""self = PyObject_NEW(pyopencv_${name}_t, &pyopencv_${name}_Type);
gen_template_call_constructor_prelude
=
Template
(
"""new (&(self->v)) Ptr<$cname>(); // init Ptr with placement new
new (&(self->v)) Ptr<$cname>(); // init Ptr with placement new
if(self) """
)
if(self) """
)
gen_template_call_constructor
=
Template
(
"""self->v.reset(new ${cname}${args})"""
)
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);
gen_template_simple_call_constructor_prelude
=
Template
(
"""if(self) """
)
if(self) """
)
gen_template_simple_call_constructor
=
Template
(
"""new (&(self->v)) ${cname}${args}"""
)
gen_template_simple_call_constructor
=
Template
(
"""new (&(self->v)) ${cname}${args}"""
)
...
@@ -189,6 +187,7 @@ static void pyopencv_${name}_specials(void)
...
@@ -189,6 +187,7 @@ static void pyopencv_${name}_specials(void)
pyopencv_${name}_Type.tp_dealloc = pyopencv_${name}_dealloc;
pyopencv_${name}_Type.tp_dealloc = pyopencv_${name}_dealloc;
pyopencv_${name}_Type.tp_repr = pyopencv_${name}_repr;
pyopencv_${name}_Type.tp_repr = pyopencv_${name}_repr;
pyopencv_${name}_Type.tp_getset = pyopencv_${name}_getseters;
pyopencv_${name}_Type.tp_getset = pyopencv_${name}_getseters;
pyopencv_${name}_Type.tp_init = (initproc)${constructor};
pyopencv_${name}_Type.tp_methods = pyopencv_${name}_methods;${extra_specials}
pyopencv_${name}_Type.tp_methods = pyopencv_${name}_methods;${extra_specials}
}
}
"""
)
"""
)
...
@@ -280,6 +279,7 @@ class ClassInfo(object):
...
@@ -280,6 +279,7 @@ class ClassInfo(object):
self
.
props
=
[]
self
.
props
=
[]
self
.
consts
=
{}
self
.
consts
=
{}
self
.
base
=
None
self
.
base
=
None
self
.
constructor
=
None
customname
=
False
customname
=
False
if
decl
:
if
decl
:
...
@@ -353,6 +353,9 @@ class ClassInfo(object):
...
@@ -353,6 +353,9 @@ class ClassInfo(object):
sorted_methods
=
list
(
self
.
methods
.
items
())
sorted_methods
=
list
(
self
.
methods
.
items
())
sorted_methods
.
sort
()
sorted_methods
.
sort
()
if
self
.
constructor
is
not
None
:
methods_code
.
write
(
self
.
constructor
.
gen_code
(
all_classes
))
for
mname
,
m
in
sorted_methods
:
for
mname
,
m
in
sorted_methods
:
methods_code
.
write
(
m
.
gen_code
(
all_classes
))
methods_code
.
write
(
m
.
gen_code
(
all_classes
))
methods_inits
.
write
(
m
.
get_tab_entry
())
methods_inits
.
write
(
m
.
get_tab_entry
())
...
@@ -361,10 +364,14 @@ class ClassInfo(object):
...
@@ -361,10 +364,14 @@ class ClassInfo(object):
if
self
.
base
and
self
.
base
in
all_classes
:
if
self
.
base
and
self
.
base
in
all_classes
:
baseptr
=
"&pyopencv_"
+
all_classes
[
self
.
base
]
.
name
+
"_Type"
baseptr
=
"&pyopencv_"
+
all_classes
[
self
.
base
]
.
name
+
"_Type"
constructor_name
=
"0"
if
self
.
constructor
is
not
None
:
constructor_name
=
self
.
constructor
.
get_wrapper_name
()
code
=
gen_template_type_impl
.
substitute
(
name
=
self
.
name
,
wname
=
self
.
wname
,
cname
=
self
.
cname
,
code
=
gen_template_type_impl
.
substitute
(
name
=
self
.
name
,
wname
=
self
.
wname
,
cname
=
self
.
cname
,
getset_code
=
getset_code
.
getvalue
(),
getset_inits
=
getset_inits
.
getvalue
(),
getset_code
=
getset_code
.
getvalue
(),
getset_inits
=
getset_inits
.
getvalue
(),
methods_code
=
methods_code
.
getvalue
(),
methods_inits
=
methods_inits
.
getvalue
(),
methods_code
=
methods_code
.
getvalue
(),
methods_inits
=
methods_inits
.
getvalue
(),
baseptr
=
baseptr
,
extra_specials
=
""
)
baseptr
=
baseptr
,
constructor
=
constructor_name
,
extra_specials
=
""
)
return
code
return
code
...
@@ -521,12 +528,13 @@ class FuncVariant(object):
...
@@ -521,12 +528,13 @@ class FuncVariant(object):
class
FuncInfo
(
object
):
class
FuncInfo
(
object
):
def
__init__
(
self
,
classname
,
name
,
cname
,
isconstructor
,
namespace
):
def
__init__
(
self
,
classname
,
name
,
cname
,
isconstructor
,
namespace
,
isclassmethod
):
self
.
classname
=
classname
self
.
classname
=
classname
self
.
name
=
name
self
.
name
=
name
self
.
cname
=
cname
self
.
cname
=
cname
self
.
isconstructor
=
isconstructor
self
.
isconstructor
=
isconstructor
self
.
namespace
=
namespace
self
.
namespace
=
namespace
self
.
isclassmethod
=
isclassmethod
self
.
variants
=
[]
self
.
variants
=
[]
def
add_variant
(
self
,
decl
):
def
add_variant
(
self
,
decl
):
...
@@ -540,11 +548,19 @@ class FuncInfo(object):
...
@@ -540,11 +548,19 @@ class FuncInfo(object):
name
=
"getelem"
name
=
"getelem"
else
:
else
:
classname
=
""
classname
=
""
if
self
.
isclassmethod
:
name
+=
"_cls"
return
"pyopencv_"
+
self
.
namespace
.
replace
(
'.'
,
'_'
)
+
'_'
+
classname
+
name
return
"pyopencv_"
+
self
.
namespace
.
replace
(
'.'
,
'_'
)
+
'_'
+
classname
+
name
def
get_wrapper_prototype
(
self
):
def
get_wrapper_prototype
(
self
,
all_classes
):
full_fname
=
self
.
get_wrapper_name
()
full_fname
=
self
.
get_wrapper_name
()
if
self
.
classname
and
not
self
.
isconstructor
:
if
self
.
isconstructor
:
return
"static int {fn_name}(pyopencv_{type_name}_t* self, PyObject* args, PyObject* kw)"
.
format
(
fn_name
=
full_fname
,
type_name
=
all_classes
[
self
.
classname
]
.
name
)
if
self
.
classname
:
self_arg
=
"self"
self_arg
=
"self"
else
:
else
:
self_arg
=
""
self_arg
=
""
...
@@ -591,12 +607,16 @@ class FuncInfo(object):
...
@@ -591,12 +607,16 @@ class FuncInfo(object):
# Convert unicode chars to xml representation, but keep as string instead of bytes
# Convert unicode chars to xml representation, but keep as string instead of bytes
full_docstring
=
full_docstring
.
encode
(
'ascii'
,
errors
=
'xmlcharrefreplace'
)
.
decode
()
full_docstring
=
full_docstring
.
encode
(
'ascii'
,
errors
=
'xmlcharrefreplace'
)
.
decode
()
return
Template
(
' {"$py_funcname", (PyCFunction)$wrap_funcname, METH_VARARGS | METH_KEYWORDS, "$py_docstring"},
\n
'
flags
=
[
"METH_VARARGS"
,
"METH_KEYWORDS"
]
if
self
.
isclassmethod
:
flags
.
append
(
"METH_CLASS"
)
return
Template
(
' {"$py_funcname", (PyCFunction)$wrap_funcname, $flags, "$py_docstring"},
\n
'
)
.
substitute
(
py_funcname
=
self
.
variants
[
0
]
.
wname
,
wrap_funcname
=
self
.
get_wrapper_name
(),
)
.
substitute
(
py_funcname
=
self
.
variants
[
0
]
.
wname
,
wrap_funcname
=
self
.
get_wrapper_name
(),
py_docstring
=
full_docstring
)
flags
=
" | "
.
join
(
flags
),
py_docstring
=
full_docstring
)
def
gen_code
(
self
,
all_classes
):
def
gen_code
(
self
,
all_classes
):
proto
=
self
.
get_wrapper_prototype
()
proto
=
self
.
get_wrapper_prototype
(
all_classes
)
code
=
"
%
s
\n
{
\n
"
%
(
proto
,)
code
=
"
%
s
\n
{
\n
"
%
(
proto
,)
code
+=
" using namespace
%
s;
\n\n
"
%
self
.
namespace
.
replace
(
'.'
,
'::'
)
code
+=
" using namespace
%
s;
\n\n
"
%
self
.
namespace
.
replace
(
'.'
,
'::'
)
...
@@ -609,7 +629,9 @@ class FuncInfo(object):
...
@@ -609,7 +629,9 @@ class FuncInfo(object):
selfinfo
=
all_classes
[
self
.
classname
]
selfinfo
=
all_classes
[
self
.
classname
]
if
not
self
.
isconstructor
:
if
not
self
.
isconstructor
:
amp
=
"&"
if
selfinfo
.
issimple
else
""
amp
=
"&"
if
selfinfo
.
issimple
else
""
if
selfinfo
.
isalgorithm
:
if
self
.
isclassmethod
:
pass
elif
selfinfo
.
isalgorithm
:
code
+=
gen_template_check_self_algo
.
substitute
(
name
=
selfinfo
.
name
,
cname
=
selfinfo
.
cname
,
amp
=
amp
)
code
+=
gen_template_check_self_algo
.
substitute
(
name
=
selfinfo
.
name
,
cname
=
selfinfo
.
cname
,
amp
=
amp
)
else
:
else
:
get
=
""
if
selfinfo
.
issimple
else
".get()"
get
=
""
if
selfinfo
.
issimple
else
".get()"
...
@@ -692,7 +714,6 @@ class FuncInfo(object):
...
@@ -692,7 +714,6 @@ class FuncInfo(object):
code_args
+=
")"
code_args
+=
")"
if
self
.
isconstructor
:
if
self
.
isconstructor
:
code_decl
+=
" pyopencv_
%
s_t* self = 0;
\n
"
%
selfinfo
.
name
if
selfinfo
.
issimple
:
if
selfinfo
.
issimple
:
templ_prelude
=
gen_template_simple_call_constructor_prelude
templ_prelude
=
gen_template_simple_call_constructor_prelude
templ
=
gen_template_simple_call_constructor
templ
=
gen_template_simple_call_constructor
...
@@ -708,7 +729,7 @@ class FuncInfo(object):
...
@@ -708,7 +729,7 @@ class FuncInfo(object):
if
v
.
rettype
:
if
v
.
rettype
:
code_decl
+=
" "
+
v
.
rettype
+
" retval;
\n
"
code_decl
+=
" "
+
v
.
rettype
+
" retval;
\n
"
code_fcall
+=
"retval = "
code_fcall
+=
"retval = "
if
ismethod
:
if
ismethod
and
not
self
.
isclassmethod
:
code_fcall
+=
"_self_->"
+
self
.
cname
code_fcall
+=
"_self_->"
+
self
.
cname
else
:
else
:
code_fcall
+=
self
.
cname
code_fcall
+=
self
.
cname
...
@@ -750,7 +771,7 @@ class FuncInfo(object):
...
@@ -750,7 +771,7 @@ class FuncInfo(object):
code_ret
=
"Py_RETURN_NONE"
code_ret
=
"Py_RETURN_NONE"
elif
len
(
v
.
py_outlist
)
==
1
:
elif
len
(
v
.
py_outlist
)
==
1
:
if
self
.
isconstructor
:
if
self
.
isconstructor
:
code_ret
=
"return
(PyObject*)self
"
code_ret
=
"return
0
"
else
:
else
:
aname
,
argno
=
v
.
py_outlist
[
0
]
aname
,
argno
=
v
.
py_outlist
[
0
]
code_ret
=
"return pyopencv_from(
%
s)"
%
(
aname
,)
code_ret
=
"return pyopencv_from(
%
s)"
%
(
aname
,)
...
@@ -773,7 +794,11 @@ class FuncInfo(object):
...
@@ -773,7 +794,11 @@ class FuncInfo(object):
else
:
else
:
# try to execute each signature
# try to execute each signature
code
+=
" PyErr_Clear();
\n\n
"
.
join
([
" {
\n
"
+
v
+
" }
\n
"
for
v
in
all_code_variants
])
code
+=
" PyErr_Clear();
\n\n
"
.
join
([
" {
\n
"
+
v
+
" }
\n
"
for
v
in
all_code_variants
])
code
+=
"
\n
return NULL;
\n
}
\n\n
"
def_ret
=
"NULL"
if
self
.
isconstructor
:
def_ret
=
"-1"
code
+=
"
\n
return
%
s;
\n
}
\n\n
"
%
def_ret
return
code
return
code
...
@@ -796,6 +821,7 @@ class PythonWrapperGenerator(object):
...
@@ -796,6 +821,7 @@ class PythonWrapperGenerator(object):
self
.
code_funcs
=
StringIO
()
self
.
code_funcs
=
StringIO
()
self
.
code_type_reg
=
StringIO
()
self
.
code_type_reg
=
StringIO
()
self
.
code_ns_reg
=
StringIO
()
self
.
code_ns_reg
=
StringIO
()
self
.
code_type_publish
=
StringIO
()
self
.
class_idx
=
0
self
.
class_idx
=
0
def
add_class
(
self
,
stype
,
name
,
decl
):
def
add_class
(
self
,
stype
,
name
,
decl
):
...
@@ -848,20 +874,32 @@ class PythonWrapperGenerator(object):
...
@@ -848,20 +874,32 @@ class PythonWrapperGenerator(object):
isclassmethod
=
True
isclassmethod
=
True
elif
m
.
startswith
(
"="
):
elif
m
.
startswith
(
"="
):
name
=
m
[
1
:]
name
=
m
[
1
:]
if
isclassmethod
:
if
isconstructor
:
name
=
"_"
.
join
(
classes
+
[
name
])
classname
=
''
elif
isconstructor
:
name
=
"_"
.
join
(
classes
[:
-
1
]
+
[
name
])
name
=
"_"
.
join
(
classes
[:
-
1
]
+
[
name
])
if
classname
and
not
isconstructor
:
if
isclassmethod
:
cname
=
barename
# Add it as a method to the class
func_map
=
self
.
classes
[
classname
]
.
methods
func_map
=
self
.
classes
[
classname
]
.
methods
else
:
func
=
func_map
.
setdefault
(
name
,
FuncInfo
(
classname
,
name
,
cname
,
isconstructor
,
namespace
,
isclassmethod
))
func
.
add_variant
(
decl
)
# Add it as global function
g_name
=
"_"
.
join
(
classes
+
[
name
])
func_map
=
self
.
namespaces
.
setdefault
(
namespace
,
Namespace
())
.
funcs
func_map
=
self
.
namespaces
.
setdefault
(
namespace
,
Namespace
())
.
funcs
func
=
func_map
.
setdefault
(
g_name
,
FuncInfo
(
""
,
g_name
,
cname
,
isconstructor
,
namespace
,
False
))
func
.
add_variant
(
decl
)
else
:
if
classname
and
not
isconstructor
:
cname
=
barename
func_map
=
self
.
classes
[
classname
]
.
methods
else
:
func_map
=
self
.
namespaces
.
setdefault
(
namespace
,
Namespace
())
.
funcs
func
=
func_map
.
setdefault
(
name
,
FuncInfo
(
classname
,
name
,
cname
,
isconstructor
,
namespace
,
isclassmethod
))
func
.
add_variant
(
decl
)
func
=
func_map
.
setdefault
(
name
,
FuncInfo
(
classname
,
name
,
cname
,
isconstructor
,
namespace
))
if
classname
and
isconstructor
:
func
.
add_variant
(
decl
)
self
.
classes
[
classname
]
.
constructor
=
func
def
gen_namespace
(
self
,
ns_name
):
def
gen_namespace
(
self
,
ns_name
):
...
@@ -870,6 +908,8 @@ class PythonWrapperGenerator(object):
...
@@ -870,6 +908,8 @@ class PythonWrapperGenerator(object):
self
.
code_ns_reg
.
write
(
'static PyMethodDef methods_
%
s[] = {
\n
'
%
wname
)
self
.
code_ns_reg
.
write
(
'static PyMethodDef methods_
%
s[] = {
\n
'
%
wname
)
for
name
,
func
in
sorted
(
ns
.
funcs
.
items
()):
for
name
,
func
in
sorted
(
ns
.
funcs
.
items
()):
if
func
.
isconstructor
:
continue
self
.
code_ns_reg
.
write
(
func
.
get_tab_entry
())
self
.
code_ns_reg
.
write
(
func
.
get_tab_entry
())
self
.
code_ns_reg
.
write
(
' {NULL, NULL}
\n
};
\n\n
'
)
self
.
code_ns_reg
.
write
(
' {NULL, NULL}
\n
};
\n\n
'
)
...
@@ -960,12 +1000,15 @@ class PythonWrapperGenerator(object):
...
@@ -960,12 +1000,15 @@ class PythonWrapperGenerator(object):
self
.
code_types
.
write
(
code
)
self
.
code_types
.
write
(
code
)
if
not
classinfo
.
ismap
:
if
not
classinfo
.
ismap
:
self
.
code_type_reg
.
write
(
"MKTYPE2(
%
s);
\n
"
%
(
classinfo
.
name
,)
)
self
.
code_type_reg
.
write
(
"MKTYPE2(
%
s);
\n
"
%
(
classinfo
.
name
,)
)
self
.
code_type_publish
.
write
(
"PUBLISH_OBJECT(
\"
{name}
\"
, pyopencv_{name}_Type);
\n
"
.
format
(
name
=
classinfo
.
name
))
# step 3: generate the code for all the global functions
# step 3: generate the code for all the global functions
for
ns_name
,
ns
in
sorted
(
self
.
namespaces
.
items
()):
for
ns_name
,
ns
in
sorted
(
self
.
namespaces
.
items
()):
if
ns_name
.
split
(
'.'
)[
0
]
!=
'cv'
:
if
ns_name
.
split
(
'.'
)[
0
]
!=
'cv'
:
continue
continue
for
name
,
func
in
sorted
(
ns
.
funcs
.
items
()):
for
name
,
func
in
sorted
(
ns
.
funcs
.
items
()):
if
func
.
isconstructor
:
continue
code
=
func
.
gen_code
(
self
.
classes
)
code
=
func
.
gen_code
(
self
.
classes
)
self
.
code_funcs
.
write
(
code
)
self
.
code_funcs
.
write
(
code
)
self
.
gen_namespace
(
ns_name
)
self
.
gen_namespace
(
ns_name
)
...
@@ -983,6 +1026,7 @@ class PythonWrapperGenerator(object):
...
@@ -983,6 +1026,7 @@ class PythonWrapperGenerator(object):
self
.
save
(
output_path
,
"pyopencv_generated_types.h"
,
self
.
code_types
)
self
.
save
(
output_path
,
"pyopencv_generated_types.h"
,
self
.
code_types
)
self
.
save
(
output_path
,
"pyopencv_generated_type_reg.h"
,
self
.
code_type_reg
)
self
.
save
(
output_path
,
"pyopencv_generated_type_reg.h"
,
self
.
code_type_reg
)
self
.
save
(
output_path
,
"pyopencv_generated_ns_reg.h"
,
self
.
code_ns_reg
)
self
.
save
(
output_path
,
"pyopencv_generated_ns_reg.h"
,
self
.
code_ns_reg
)
self
.
save
(
output_path
,
"pyopencv_generated_type_publish.h"
,
self
.
code_type_publish
)
if
__name__
==
"__main__"
:
if
__name__
==
"__main__"
:
srcfiles
=
hdr_parser
.
opencv_hdr_list
srcfiles
=
hdr_parser
.
opencv_hdr_list
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment