|
|
|
@ -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)"); |
|
|
|
|
""") |
|
|
|
|
|
|
|
|
|
gen_template_call_constructor_prelude = Template("""self = PyObject_NEW(pyopencv_${name}_t, &pyopencv_${name}_Type); |
|
|
|
|
new (&(self->v)) Ptr<$cname>(); // init Ptr with placement new |
|
|
|
|
gen_template_call_constructor_prelude = Template("""new (&(self->v)) Ptr<$cname>(); // init Ptr with placement new |
|
|
|
|
if(self) """) |
|
|
|
|
|
|
|
|
|
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_prelude = Template("""if(self) """) |
|
|
|
|
|
|
|
|
|
gen_template_simple_call_constructor = Template("""new (&(self->v)) ${cname}${args}""") |
|
|
|
|
|
|
|
|
@ -189,6 +187,7 @@ static void pyopencv_${name}_specials(void) |
|
|
|
|
pyopencv_${name}_Type.tp_dealloc = pyopencv_${name}_dealloc; |
|
|
|
|
pyopencv_${name}_Type.tp_repr = pyopencv_${name}_repr; |
|
|
|
|
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} |
|
|
|
|
} |
|
|
|
|
""") |
|
|
|
@ -280,6 +279,7 @@ class ClassInfo(object): |
|
|
|
|
self.props = [] |
|
|
|
|
self.consts = {} |
|
|
|
|
self.base = None |
|
|
|
|
self.constructor = None |
|
|
|
|
customname = False |
|
|
|
|
|
|
|
|
|
if decl: |
|
|
|
@ -353,6 +353,9 @@ class ClassInfo(object): |
|
|
|
|
sorted_methods = list(self.methods.items()) |
|
|
|
|
sorted_methods.sort() |
|
|
|
|
|
|
|
|
|
if self.constructor is not None: |
|
|
|
|
methods_code.write(self.constructor.gen_code(all_classes)) |
|
|
|
|
|
|
|
|
|
for mname, m in sorted_methods: |
|
|
|
|
methods_code.write(m.gen_code(all_classes)) |
|
|
|
|
methods_inits.write(m.get_tab_entry()) |
|
|
|
@ -361,10 +364,14 @@ class ClassInfo(object): |
|
|
|
|
if self.base and self.base in all_classes: |
|
|
|
|
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, |
|
|
|
|
getset_code=getset_code.getvalue(), getset_inits=getset_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 |
|
|
|
|
|
|
|
|
@ -521,12 +528,13 @@ class FuncVariant(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.name = name |
|
|
|
|
self.cname = cname |
|
|
|
|
self.isconstructor = isconstructor |
|
|
|
|
self.namespace = namespace |
|
|
|
|
self.isclassmethod = isclassmethod |
|
|
|
|
self.variants = [] |
|
|
|
|
|
|
|
|
|
def add_variant(self, decl): |
|
|
|
@ -540,11 +548,19 @@ class FuncInfo(object): |
|
|
|
|
name = "getelem" |
|
|
|
|
else: |
|
|
|
|
classname = "" |
|
|
|
|
|
|
|
|
|
if self.isclassmethod: |
|
|
|
|
name += "_cls" |
|
|
|
|
|
|
|
|
|
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() |
|
|
|
|
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" |
|
|
|
|
else: |
|
|
|
|
self_arg = "" |
|
|
|
@ -591,12 +607,16 @@ class FuncInfo(object): |
|
|
|
|
# Convert unicode chars to xml representation, but keep as string instead of bytes |
|
|
|
|
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(), |
|
|
|
|
py_docstring = full_docstring) |
|
|
|
|
flags = " | ".join(flags), py_docstring = full_docstring) |
|
|
|
|
|
|
|
|
|
def gen_code(self, all_classes): |
|
|
|
|
proto = self.get_wrapper_prototype() |
|
|
|
|
proto = self.get_wrapper_prototype(all_classes) |
|
|
|
|
code = "%s\n{\n" % (proto,) |
|
|
|
|
code += " using namespace %s;\n\n" % self.namespace.replace('.', '::') |
|
|
|
|
|
|
|
|
@ -609,7 +629,9 @@ class FuncInfo(object): |
|
|
|
|
selfinfo = all_classes[self.classname] |
|
|
|
|
if not self.isconstructor: |
|
|
|
|
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) |
|
|
|
|
else: |
|
|
|
|
get = "" if selfinfo.issimple else ".get()" |
|
|
|
@ -692,7 +714,6 @@ class FuncInfo(object): |
|
|
|
|
code_args += ")" |
|
|
|
|
|
|
|
|
|
if self.isconstructor: |
|
|
|
|
code_decl += " pyopencv_%s_t* self = 0;\n" % selfinfo.name |
|
|
|
|
if selfinfo.issimple: |
|
|
|
|
templ_prelude = gen_template_simple_call_constructor_prelude |
|
|
|
|
templ = gen_template_simple_call_constructor |
|
|
|
@ -708,7 +729,7 @@ class FuncInfo(object): |
|
|
|
|
if v.rettype: |
|
|
|
|
code_decl += " " + v.rettype + " retval;\n" |
|
|
|
|
code_fcall += "retval = " |
|
|
|
|
if ismethod: |
|
|
|
|
if ismethod and not self.isclassmethod: |
|
|
|
|
code_fcall += "_self_->" + self.cname |
|
|
|
|
else: |
|
|
|
|
code_fcall += self.cname |
|
|
|
@ -750,7 +771,7 @@ class FuncInfo(object): |
|
|
|
|
code_ret = "Py_RETURN_NONE" |
|
|
|
|
elif len(v.py_outlist) == 1: |
|
|
|
|
if self.isconstructor: |
|
|
|
|
code_ret = "return (PyObject*)self" |
|
|
|
|
code_ret = "return 0" |
|
|
|
|
else: |
|
|
|
|
aname, argno = v.py_outlist[0] |
|
|
|
|
code_ret = "return pyopencv_from(%s)" % (aname,) |
|
|
|
@ -773,7 +794,11 @@ class FuncInfo(object): |
|
|
|
|
else: |
|
|
|
|
# try to execute each signature |
|
|
|
|
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 |
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -796,6 +821,7 @@ class PythonWrapperGenerator(object): |
|
|
|
|
self.code_funcs = StringIO() |
|
|
|
|
self.code_type_reg = StringIO() |
|
|
|
|
self.code_ns_reg = StringIO() |
|
|
|
|
self.code_type_publish = StringIO() |
|
|
|
|
self.class_idx = 0 |
|
|
|
|
|
|
|
|
|
def add_class(self, stype, name, decl): |
|
|
|
@ -848,20 +874,32 @@ class PythonWrapperGenerator(object): |
|
|
|
|
isclassmethod = True |
|
|
|
|
elif m.startswith("="): |
|
|
|
|
name = m[1:] |
|
|
|
|
if isclassmethod: |
|
|
|
|
name = "_".join(classes+[name]) |
|
|
|
|
classname = '' |
|
|
|
|
elif isconstructor: |
|
|
|
|
if isconstructor: |
|
|
|
|
name = "_".join(classes[:-1]+[name]) |
|
|
|
|
|
|
|
|
|
if classname and not isconstructor: |
|
|
|
|
cname = barename |
|
|
|
|
if isclassmethod: |
|
|
|
|
# Add it as a method to the class |
|
|
|
|
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 = 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)) |
|
|
|
|
func.add_variant(decl) |
|
|
|
|
if classname and isconstructor: |
|
|
|
|
self.classes[classname].constructor = func |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def gen_namespace(self, ns_name): |
|
|
|
@ -870,6 +908,8 @@ class PythonWrapperGenerator(object): |
|
|
|
|
|
|
|
|
|
self.code_ns_reg.write('static PyMethodDef methods_%s[] = {\n'%wname) |
|
|
|
|
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(' {NULL, NULL}\n};\n\n') |
|
|
|
|
|
|
|
|
@ -960,12 +1000,15 @@ class PythonWrapperGenerator(object): |
|
|
|
|
self.code_types.write(code) |
|
|
|
|
if not classinfo.ismap: |
|
|
|
|
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 |
|
|
|
|
for ns_name, ns in sorted(self.namespaces.items()): |
|
|
|
|
if ns_name.split('.')[0] != 'cv': |
|
|
|
|
continue |
|
|
|
|
for name, func in sorted(ns.funcs.items()): |
|
|
|
|
if func.isconstructor: |
|
|
|
|
continue |
|
|
|
|
code = func.gen_code(self.classes) |
|
|
|
|
self.code_funcs.write(code) |
|
|
|
|
self.gen_namespace(ns_name) |
|
|
|
@ -983,6 +1026,7 @@ class PythonWrapperGenerator(object): |
|
|
|
|
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) |
|
|
|
|
self.save(output_path, "pyopencv_generated_type_publish.h", self.code_type_publish) |
|
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
|
|
srcfiles = hdr_parser.opencv_hdr_list |
|
|
|
|