|
|
|
@ -10,19 +10,23 @@ if sys.version_info[0] >= 3: |
|
|
|
|
else: |
|
|
|
|
from cStringIO import StringIO |
|
|
|
|
|
|
|
|
|
forbidden_arg_types = ["void*"] |
|
|
|
|
|
|
|
|
|
ignored_arg_types = ["RNG*"] |
|
|
|
|
|
|
|
|
|
pass_by_val_types = ["Point*", "Point2f*", "Rect*", "String*", "double*", "float*", "int*"] |
|
|
|
|
|
|
|
|
|
gen_template_check_self = Template(""" $cname* _self_ = NULL; |
|
|
|
|
if(PyObject_TypeCheck(self, &pyopencv_${name}_Type)) |
|
|
|
|
_self_ = ${amp}((pyopencv_${name}_t*)self)->v${get}; |
|
|
|
|
if (_self_ == NULL) |
|
|
|
|
if (!_self_) |
|
|
|
|
return failmsgp("Incorrect type of self (must be '${name}' or its derivative)"); |
|
|
|
|
""") |
|
|
|
|
|
|
|
|
|
gen_template_check_self_algo = Template(""" $cname* _self_ = NULL; |
|
|
|
|
if(PyObject_TypeCheck(self, &pyopencv_${name}_Type)) |
|
|
|
|
_self_ = dynamic_cast<$cname*>(${amp}((pyopencv_${name}_t*)self)->v.get()); |
|
|
|
|
if (_self_ == NULL) |
|
|
|
|
if (!_self_) |
|
|
|
|
return failmsgp("Incorrect type of self (must be '${name}' or its derivative)"); |
|
|
|
|
""") |
|
|
|
|
|
|
|
|
@ -68,27 +72,40 @@ static void pyopencv_${name}_dealloc(PyObject* self) |
|
|
|
|
PyObject_Del(self); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
template<> PyObject* pyopencv_from(const ${cname}& r) |
|
|
|
|
template<> |
|
|
|
|
struct PyOpenCV_Converter< ${cname} > |
|
|
|
|
{ |
|
|
|
|
static PyObject* from(const ${cname}& r) |
|
|
|
|
{ |
|
|
|
|
pyopencv_${name}_t *m = PyObject_NEW(pyopencv_${name}_t, &pyopencv_${name}_Type); |
|
|
|
|
new (&m->v) ${cname}(r); //Copy constructor |
|
|
|
|
return (PyObject*)m; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
template<> bool pyopencv_to(PyObject* src, ${cname}& dst, const char* name) |
|
|
|
|
{ |
|
|
|
|
if( src == NULL || src == Py_None ) |
|
|
|
|
static bool to(PyObject* src, ${cname}& dst, const char* name) |
|
|
|
|
{ |
|
|
|
|
if(!src || src == Py_None) |
|
|
|
|
return true; |
|
|
|
|
if(!PyObject_TypeCheck(src, &pyopencv_${name}_Type)) |
|
|
|
|
if(PyObject_TypeCheck(src, &pyopencv_${name}_Type)) |
|
|
|
|
{ |
|
|
|
|
dst = ((pyopencv_${name}_t*)src)->v; |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
failmsg("Expected ${cname} for argument '%%s'", name); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
dst = ((pyopencv_${name}_t*)src)->v; |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
""" % head_init_str) |
|
|
|
|
|
|
|
|
|
gen_template_mappable = Template(""" |
|
|
|
|
{ |
|
|
|
|
${mappable} _src; |
|
|
|
|
if (pyopencv_to(src, _src, name)) |
|
|
|
|
{ |
|
|
|
|
return cv_mappable_to(_src, dst); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
""") |
|
|
|
|
|
|
|
|
|
gen_template_type_decl = Template(""" |
|
|
|
|
struct pyopencv_${name}_t |
|
|
|
@ -110,26 +127,31 @@ static void pyopencv_${name}_dealloc(PyObject* self) |
|
|
|
|
PyObject_Del(self); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
template<> PyObject* pyopencv_from(const Ptr<${cname}>& r) |
|
|
|
|
template<> |
|
|
|
|
struct PyOpenCV_Converter< Ptr<${cname}> > |
|
|
|
|
{ |
|
|
|
|
static PyObject* 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 |
|
|
|
|
m->v = r; |
|
|
|
|
return (PyObject*)m; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
template<> bool pyopencv_to(PyObject* src, Ptr<${cname}>& dst, const char* name) |
|
|
|
|
{ |
|
|
|
|
if( src == NULL || src == Py_None ) |
|
|
|
|
static bool to(PyObject* src, Ptr<${cname}>& dst, const char* name) |
|
|
|
|
{ |
|
|
|
|
if(!src || src == Py_None) |
|
|
|
|
return true; |
|
|
|
|
if(!PyObject_TypeCheck(src, &pyopencv_${name}_Type)) |
|
|
|
|
if(PyObject_TypeCheck(src, &pyopencv_${name}_Type)) |
|
|
|
|
{ |
|
|
|
|
dst = ((pyopencv_${name}_t*)src)->v.dynamicCast<${cname}>(); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
${mappable_code} |
|
|
|
|
failmsg("Expected ${cname} for argument '%%s'", name); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
dst = ((pyopencv_${name}_t*)src)->v.dynamicCast<${cname}>(); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
""" % head_init_str) |
|
|
|
|
|
|
|
|
@ -192,7 +214,7 @@ gen_template_get_prop_algo = Template(""" |
|
|
|
|
static PyObject* pyopencv_${name}_get_${member}(pyopencv_${name}_t* p, void *closure) |
|
|
|
|
{ |
|
|
|
|
$cname* _self_ = dynamic_cast<$cname*>(p->v.get()); |
|
|
|
|
if (_self_ == NULL) |
|
|
|
|
if (!_self_) |
|
|
|
|
return failmsgp("Incorrect type of object (must be '${name}' or its derivative)"); |
|
|
|
|
return pyopencv_from(_self_${access}${member}); |
|
|
|
|
} |
|
|
|
@ -201,7 +223,7 @@ static PyObject* pyopencv_${name}_get_${member}(pyopencv_${name}_t* p, void *clo |
|
|
|
|
gen_template_set_prop = Template(""" |
|
|
|
|
static int pyopencv_${name}_set_${member}(pyopencv_${name}_t* p, PyObject *value, void *closure) |
|
|
|
|
{ |
|
|
|
|
if (value == NULL) |
|
|
|
|
if (!value) |
|
|
|
|
{ |
|
|
|
|
PyErr_SetString(PyExc_TypeError, "Cannot delete the ${member} attribute"); |
|
|
|
|
return -1; |
|
|
|
@ -213,13 +235,13 @@ static int pyopencv_${name}_set_${member}(pyopencv_${name}_t* p, PyObject *value |
|
|
|
|
gen_template_set_prop_algo = Template(""" |
|
|
|
|
static int pyopencv_${name}_set_${member}(pyopencv_${name}_t* p, PyObject *value, void *closure) |
|
|
|
|
{ |
|
|
|
|
if (value == NULL) |
|
|
|
|
if (!value) |
|
|
|
|
{ |
|
|
|
|
PyErr_SetString(PyExc_TypeError, "Cannot delete the ${member} attribute"); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
$cname* _self_ = dynamic_cast<$cname*>(p->v.get()); |
|
|
|
|
if (_self_ == NULL) |
|
|
|
|
if (!_self_) |
|
|
|
|
{ |
|
|
|
|
failmsgp("Incorrect type of object (must be '${name}' or its derivative)"); |
|
|
|
|
return -1; |
|
|
|
@ -265,6 +287,7 @@ class ClassInfo(object): |
|
|
|
|
self.isalgorithm = False |
|
|
|
|
self.methods = {} |
|
|
|
|
self.props = [] |
|
|
|
|
self.mappables = [] |
|
|
|
|
self.consts = {} |
|
|
|
|
self.base = None |
|
|
|
|
self.constructor = None |
|
|
|
@ -402,7 +425,7 @@ class ArgInfo(object): |
|
|
|
|
self.py_outputarg = False |
|
|
|
|
|
|
|
|
|
def isbig(self): |
|
|
|
|
return self.tp == "Mat" or self.tp == "vector_Mat"\ |
|
|
|
|
return self.tp == "Mat" or self.tp == "vector_Mat" or self.tp == "cuda::GpuMat"\ |
|
|
|
|
or self.tp == "UMat" or self.tp == "vector_UMat" # or self.tp.startswith("vector") |
|
|
|
|
|
|
|
|
|
def crepr(self): |
|
|
|
@ -410,10 +433,11 @@ class ArgInfo(object): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class FuncVariant(object): |
|
|
|
|
def __init__(self, classname, name, decl, isconstructor): |
|
|
|
|
def __init__(self, classname, name, decl, isconstructor, isphantom=False): |
|
|
|
|
self.classname = classname |
|
|
|
|
self.name = self.wname = name |
|
|
|
|
self.isconstructor = isconstructor |
|
|
|
|
self.isphantom = isphantom |
|
|
|
|
|
|
|
|
|
self.docstring = decl[5] |
|
|
|
|
|
|
|
|
@ -461,6 +485,7 @@ class FuncVariant(object): |
|
|
|
|
argno += 1 |
|
|
|
|
if a.name in self.array_counters: |
|
|
|
|
continue |
|
|
|
|
assert not a.tp in forbidden_arg_types, 'Forbidden type "{}" for argument "{}" in "{}" ("{}")'.format(a.tp, a.name, self.name, self.classname) |
|
|
|
|
if a.tp in ignored_arg_types: |
|
|
|
|
continue |
|
|
|
|
if a.returnarg: |
|
|
|
@ -520,17 +545,17 @@ class FuncVariant(object): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class FuncInfo(object): |
|
|
|
|
def __init__(self, classname, name, cname, isconstructor, namespace, isclassmethod): |
|
|
|
|
def __init__(self, classname, name, cname, isconstructor, namespace, is_static): |
|
|
|
|
self.classname = classname |
|
|
|
|
self.name = name |
|
|
|
|
self.cname = cname |
|
|
|
|
self.isconstructor = isconstructor |
|
|
|
|
self.namespace = namespace |
|
|
|
|
self.isclassmethod = isclassmethod |
|
|
|
|
self.is_static = is_static |
|
|
|
|
self.variants = [] |
|
|
|
|
|
|
|
|
|
def add_variant(self, decl): |
|
|
|
|
self.variants.append(FuncVariant(self.classname, self.name, decl, self.isconstructor)) |
|
|
|
|
def add_variant(self, decl, isphantom=False): |
|
|
|
|
self.variants.append(FuncVariant(self.classname, self.name, decl, self.isconstructor, isphantom)) |
|
|
|
|
|
|
|
|
|
def get_wrapper_name(self): |
|
|
|
|
name = self.name |
|
|
|
@ -541,8 +566,8 @@ class FuncInfo(object): |
|
|
|
|
else: |
|
|
|
|
classname = "" |
|
|
|
|
|
|
|
|
|
if self.isclassmethod: |
|
|
|
|
name += "_cls" |
|
|
|
|
if self.is_static: |
|
|
|
|
name += "_static" |
|
|
|
|
|
|
|
|
|
return "pyopencv_" + self.namespace.replace('.','_') + '_' + classname + name |
|
|
|
|
|
|
|
|
@ -601,7 +626,7 @@ class FuncInfo(object): |
|
|
|
|
|
|
|
|
|
return Template(' {"$py_funcname", CV_PY_FN_WITH_KW_($wrap_funcname, $flags), "$py_docstring"},\n' |
|
|
|
|
).substitute(py_funcname = self.variants[0].wname, wrap_funcname=self.get_wrapper_name(), |
|
|
|
|
flags = 'METH_CLASS' if self.isclassmethod else '0', py_docstring = full_docstring) |
|
|
|
|
flags = 'METH_STATIC' if self.is_static else '0', py_docstring = full_docstring) |
|
|
|
|
|
|
|
|
|
def gen_code(self, codegen): |
|
|
|
|
all_classes = codegen.classes |
|
|
|
@ -618,7 +643,7 @@ class FuncInfo(object): |
|
|
|
|
selfinfo = all_classes[self.classname] |
|
|
|
|
if not self.isconstructor: |
|
|
|
|
amp = "&" if selfinfo.issimple else "" |
|
|
|
|
if self.isclassmethod: |
|
|
|
|
if self.is_static: |
|
|
|
|
pass |
|
|
|
|
elif selfinfo.isalgorithm: |
|
|
|
|
code += gen_template_check_self_algo.substitute(name=selfinfo.name, cname=selfinfo.cname, amp=amp) |
|
|
|
@ -638,6 +663,9 @@ class FuncInfo(object): |
|
|
|
|
all_cargs = [] |
|
|
|
|
parse_arglist = [] |
|
|
|
|
|
|
|
|
|
if v.isphantom and ismethod and not self.is_static: |
|
|
|
|
code_args += "_self_" |
|
|
|
|
|
|
|
|
|
# declare all the C function arguments, |
|
|
|
|
# add necessary conversions from Python objects to code_cvt_list, |
|
|
|
|
# form the function/method call, |
|
|
|
@ -646,7 +674,7 @@ class FuncInfo(object): |
|
|
|
|
if a.tp in ignored_arg_types: |
|
|
|
|
defval = a.defval |
|
|
|
|
if not defval and a.tp.endswith("*"): |
|
|
|
|
defval = 0 |
|
|
|
|
defval = "0" |
|
|
|
|
assert defval |
|
|
|
|
if not code_args.endswith("("): |
|
|
|
|
code_args += ", " |
|
|
|
@ -656,15 +684,15 @@ class FuncInfo(object): |
|
|
|
|
tp1 = tp = a.tp |
|
|
|
|
amp = "" |
|
|
|
|
defval0 = "" |
|
|
|
|
if tp.endswith("*"): |
|
|
|
|
if tp in pass_by_val_types: |
|
|
|
|
tp = tp1 = tp[:-1] |
|
|
|
|
amp = "&" |
|
|
|
|
if tp.endswith("*"): |
|
|
|
|
defval0 = "0" |
|
|
|
|
tp1 = tp.replace("*", "_ptr") |
|
|
|
|
if tp1.endswith("*"): |
|
|
|
|
print("Error: type with star: a.tp=%s, tp=%s, tp1=%s" % (a.tp, tp, tp1)) |
|
|
|
|
sys.exit(-1) |
|
|
|
|
tp_candidates = [a.tp, normalize_class_name(self.namespace + "." + a.tp)] |
|
|
|
|
if any(tp in codegen.enums.keys() for tp in tp_candidates): |
|
|
|
|
defval0 = "static_cast<%s>(%d)" % (a.tp, 0) |
|
|
|
|
|
|
|
|
|
amapping = simple_argtype_mapping.get(tp, (tp, "O", defval0)) |
|
|
|
|
parse_name = a.name |
|
|
|
@ -686,6 +714,9 @@ class FuncInfo(object): |
|
|
|
|
if "UMat" in tp: |
|
|
|
|
if "Mat" in defval and "UMat" not in defval: |
|
|
|
|
defval = defval.replace("Mat", "UMat") |
|
|
|
|
if "cuda::GpuMat" in tp: |
|
|
|
|
if "Mat" in defval and "GpuMat" not in defval: |
|
|
|
|
defval = defval.replace("Mat", "cuda::GpuMat") |
|
|
|
|
# "tp arg = tp();" is equivalent to "tp arg;" in the case of complex types |
|
|
|
|
if defval == tp + "()" and amapping[1] == "O": |
|
|
|
|
defval = "" |
|
|
|
@ -712,13 +743,15 @@ class FuncInfo(object): |
|
|
|
|
|
|
|
|
|
code_prelude = templ_prelude.substitute(name=selfinfo.name, cname=selfinfo.cname) |
|
|
|
|
code_fcall = templ.substitute(name=selfinfo.name, cname=selfinfo.cname, args=code_args) |
|
|
|
|
if v.isphantom: |
|
|
|
|
code_fcall = code_fcall.replace("new " + selfinfo.cname, self.cname.replace("::", "_")) |
|
|
|
|
else: |
|
|
|
|
code_prelude = "" |
|
|
|
|
code_fcall = "" |
|
|
|
|
if v.rettype: |
|
|
|
|
code_decl += " " + v.rettype + " retval;\n" |
|
|
|
|
code_fcall += "retval = " |
|
|
|
|
if ismethod and not self.isclassmethod: |
|
|
|
|
if not v.isphantom and ismethod and not self.is_static: |
|
|
|
|
code_fcall += "_self_->" + self.cname |
|
|
|
|
else: |
|
|
|
|
code_fcall += self.cname |
|
|
|
@ -754,7 +787,7 @@ class FuncInfo(object): |
|
|
|
|
parse_arglist = ", ".join(["&" + all_cargs[argno][1] for aname, argno in v.py_arglist]), |
|
|
|
|
code_cvt = " &&\n ".join(code_cvt_list)) |
|
|
|
|
else: |
|
|
|
|
code_parse = "if(PyObject_Size(args) == 0 && (kw == NULL || PyObject_Size(kw) == 0))" |
|
|
|
|
code_parse = "if(PyObject_Size(args) == 0 && (!kw || PyObject_Size(kw) == 0))" |
|
|
|
|
|
|
|
|
|
if len(v.py_outlist) == 0: |
|
|
|
|
code_ret = "Py_RETURN_NONE" |
|
|
|
@ -799,7 +832,7 @@ class FuncInfo(object): |
|
|
|
|
#if dump: pprint(vars(classinfo)) |
|
|
|
|
if self.isconstructor: |
|
|
|
|
py_name = 'cv.' + classinfo.wname |
|
|
|
|
elif self.isclassmethod: |
|
|
|
|
elif self.is_static: |
|
|
|
|
py_name = '.'.join([self.namespace, classinfo.sname + '_' + self.variants[0].wname]) |
|
|
|
|
else: |
|
|
|
|
cname = classinfo.cname + '::' + cname |
|
|
|
@ -833,7 +866,9 @@ class PythonWrapperGenerator(object): |
|
|
|
|
self.classes = {} |
|
|
|
|
self.namespaces = {} |
|
|
|
|
self.consts = {} |
|
|
|
|
self.enums = {} |
|
|
|
|
self.code_include = StringIO() |
|
|
|
|
self.code_enums = StringIO() |
|
|
|
|
self.code_types = StringIO() |
|
|
|
|
self.code_funcs = StringIO() |
|
|
|
|
self.code_type_reg = StringIO() |
|
|
|
@ -890,6 +925,18 @@ class PythonWrapperGenerator(object): |
|
|
|
|
py_signatures.append(dict(name=py_name, value=value)) |
|
|
|
|
#print(cname + ' => ' + str(py_name) + ' (value=' + value + ')') |
|
|
|
|
|
|
|
|
|
def add_enum(self, name, decl): |
|
|
|
|
wname = normalize_class_name(name) |
|
|
|
|
if wname.endswith("<unnamed>"): |
|
|
|
|
wname = None |
|
|
|
|
else: |
|
|
|
|
self.enums[wname] = name |
|
|
|
|
const_decls = decl[3] |
|
|
|
|
|
|
|
|
|
for decl in const_decls: |
|
|
|
|
name = decl[0] |
|
|
|
|
self.add_const(name.replace("const ", "").strip(), decl) |
|
|
|
|
|
|
|
|
|
def add_func(self, decl): |
|
|
|
|
namespace, classes, barename = self.split_decl_name(decl[0]) |
|
|
|
|
cname = "::".join(namespace+classes+[barename]) |
|
|
|
@ -902,35 +949,46 @@ class PythonWrapperGenerator(object): |
|
|
|
|
namespace = '.'.join(namespace) |
|
|
|
|
|
|
|
|
|
isconstructor = name == bareclassname |
|
|
|
|
isclassmethod = False |
|
|
|
|
is_static = False |
|
|
|
|
isphantom = False |
|
|
|
|
mappable = None |
|
|
|
|
for m in decl[2]: |
|
|
|
|
if m == "/S": |
|
|
|
|
isclassmethod = True |
|
|
|
|
is_static = True |
|
|
|
|
elif m == "/phantom": |
|
|
|
|
isphantom = True |
|
|
|
|
cname = cname.replace("::", "_") |
|
|
|
|
elif m.startswith("="): |
|
|
|
|
name = m[1:] |
|
|
|
|
elif m.startswith("/mappable="): |
|
|
|
|
mappable = m[10:] |
|
|
|
|
self.classes[classname].mappables.append(mappable) |
|
|
|
|
return |
|
|
|
|
|
|
|
|
|
if isconstructor: |
|
|
|
|
name = "_".join(classes[:-1]+[name]) |
|
|
|
|
|
|
|
|
|
if isclassmethod: |
|
|
|
|
if is_static: |
|
|
|
|
# Add it as a method to the class |
|
|
|
|
func_map = self.classes[classname].methods |
|
|
|
|
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, is_static)) |
|
|
|
|
func.add_variant(decl, isphantom) |
|
|
|
|
|
|
|
|
|
# Add it as global function |
|
|
|
|
g_name = "_".join(classes+[name]) |
|
|
|
|
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) |
|
|
|
|
func.add_variant(decl, isphantom) |
|
|
|
|
else: |
|
|
|
|
if classname and not isconstructor: |
|
|
|
|
if not isphantom: |
|
|
|
|
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, is_static)) |
|
|
|
|
func.add_variant(decl, isphantom) |
|
|
|
|
|
|
|
|
|
if classname and isconstructor: |
|
|
|
|
self.classes[classname].constructor = func |
|
|
|
@ -949,10 +1007,10 @@ class PythonWrapperGenerator(object): |
|
|
|
|
|
|
|
|
|
self.code_ns_reg.write('static ConstDef consts_%s[] = {\n'%wname) |
|
|
|
|
for name, cname in sorted(ns.consts.items()): |
|
|
|
|
self.code_ns_reg.write(' {"%s", %s},\n'%(name, cname)) |
|
|
|
|
self.code_ns_reg.write(' {"%s", static_cast<long>(%s)},\n'%(name, cname)) |
|
|
|
|
compat_name = re.sub(r"([a-z])([A-Z])", r"\1_\2", name).upper() |
|
|
|
|
if name != compat_name: |
|
|
|
|
self.code_ns_reg.write(' {"%s", %s},\n'%(compat_name, cname)) |
|
|
|
|
self.code_ns_reg.write(' {"%s", static_cast<long>(%s)},\n'%(compat_name, cname)) |
|
|
|
|
self.code_ns_reg.write(' {NULL, 0}\n};\n\n') |
|
|
|
|
|
|
|
|
|
def gen_namespaces_reg(self): |
|
|
|
@ -963,6 +1021,21 @@ class PythonWrapperGenerator(object): |
|
|
|
|
self.code_ns_reg.write(' init_submodule(root, MODULESTR"%s", methods_%s, consts_%s);\n' % (ns_name[2:], wname, wname)) |
|
|
|
|
self.code_ns_reg.write('};\n') |
|
|
|
|
|
|
|
|
|
def gen_enum_reg(self, enum_name): |
|
|
|
|
name_seg = enum_name.split(".") |
|
|
|
|
is_enum_class = False |
|
|
|
|
if len(name_seg) >= 2 and name_seg[-1] == name_seg[-2]: |
|
|
|
|
enum_name = ".".join(name_seg[:-1]) |
|
|
|
|
is_enum_class = True |
|
|
|
|
|
|
|
|
|
wname = normalize_class_name(enum_name) |
|
|
|
|
cname = enum_name.replace(".", "::") |
|
|
|
|
|
|
|
|
|
code = "" |
|
|
|
|
if re.sub(r"^cv\.", "", enum_name) != wname: |
|
|
|
|
code += "typedef enum {0} {1};\n".format(cname, wname) |
|
|
|
|
code += "CV_PY_FROM_ENUM({0});\nCV_PY_TO_ENUM({0});\n\n".format(wname) |
|
|
|
|
self.code_enums.write(code) |
|
|
|
|
|
|
|
|
|
def save(self, path, name, buf): |
|
|
|
|
with open(path + "/" + name, "wt") as f: |
|
|
|
@ -975,13 +1048,14 @@ class PythonWrapperGenerator(object): |
|
|
|
|
|
|
|
|
|
def gen(self, srcfiles, output_path): |
|
|
|
|
self.clear() |
|
|
|
|
self.parser = hdr_parser.CppHeaderParser(generate_umat_decls=True) |
|
|
|
|
self.parser = hdr_parser.CppHeaderParser(generate_umat_decls=True, generate_gpumat_decls=False) |
|
|
|
|
|
|
|
|
|
# step 1: scan the headers and build more descriptive maps of classes, consts, functions |
|
|
|
|
for hdr in srcfiles: |
|
|
|
|
decls = self.parser.parse(hdr) |
|
|
|
|
if len(decls) == 0: |
|
|
|
|
continue |
|
|
|
|
if hdr.find('opencv2/') >= 0: #Avoid including the shadow files |
|
|
|
|
self.code_include.write( '#include "{0}"\n'.format(hdr[hdr.rindex('opencv2/'):]) ) |
|
|
|
|
for decl in decls: |
|
|
|
|
name = decl[0] |
|
|
|
@ -994,6 +1068,9 @@ class PythonWrapperGenerator(object): |
|
|
|
|
elif name.startswith("const"): |
|
|
|
|
# constant |
|
|
|
|
self.add_const(name.replace("const ", "").strip(), decl) |
|
|
|
|
elif name.startswith("enum"): |
|
|
|
|
# enum |
|
|
|
|
self.add_enum(name.rsplit(" ", 1)[1], decl) |
|
|
|
|
else: |
|
|
|
|
# function |
|
|
|
|
self.add_func(decl) |
|
|
|
@ -1043,8 +1120,11 @@ class PythonWrapperGenerator(object): |
|
|
|
|
templ = gen_template_simple_type_decl |
|
|
|
|
else: |
|
|
|
|
templ = gen_template_type_decl |
|
|
|
|
mappable_code = "\n".join([ |
|
|
|
|
gen_template_mappable.substitute(cname=classinfo.cname, mappable=mappable) |
|
|
|
|
for mappable in classinfo.mappables]) |
|
|
|
|
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))) |
|
|
|
|
cname1=("cv::Algorithm" if classinfo.isalgorithm else classinfo.cname), mappable_code=mappable_code)) |
|
|
|
|
|
|
|
|
|
# register classes in the same order as they have been declared. |
|
|
|
|
# this way, base classes will be registered in Python before their derivatives. |
|
|
|
@ -1070,7 +1150,13 @@ class PythonWrapperGenerator(object): |
|
|
|
|
self.gen_namespace(ns_name) |
|
|
|
|
self.gen_namespaces_reg() |
|
|
|
|
|
|
|
|
|
# step 4: generate the code for constants |
|
|
|
|
# step 4: generate the code for enum types |
|
|
|
|
enumlist = list(self.enums.values()) |
|
|
|
|
enumlist.sort() |
|
|
|
|
for name in enumlist: |
|
|
|
|
self.gen_enum_reg(name) |
|
|
|
|
|
|
|
|
|
# step 5: generate the code for constants |
|
|
|
|
constlist = list(self.consts.items()) |
|
|
|
|
constlist.sort() |
|
|
|
|
for name, constinfo in constlist: |
|
|
|
@ -1079,6 +1165,7 @@ class PythonWrapperGenerator(object): |
|
|
|
|
# That's it. Now save all the files |
|
|
|
|
self.save(output_path, "pyopencv_generated_include.h", self.code_include) |
|
|
|
|
self.save(output_path, "pyopencv_generated_funcs.h", self.code_funcs) |
|
|
|
|
self.save(output_path, "pyopencv_generated_enums.h", self.code_enums) |
|
|
|
|
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_ns_reg.h", self.code_ns_reg) |
|
|
|
|