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}""")
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}
}
""")
self.props = []
self.consts = {}
self.base = None
+ self.constructor = None
customname = False
if decl:
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())
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
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):
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 = ""
# 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('.', '::')
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()"
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
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
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,)
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
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):
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):
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')
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)
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