diff --git a/modules/java/generator/gen_java.py b/modules/java/generator/gen_java.py index 279a2e140b..6c604ed04b 100755 --- a/modules/java/generator/gen_java.py +++ b/modules/java/generator/gen_java.py @@ -123,7 +123,8 @@ T_CPP_MODULE = Template(read_contents(os.path.join(SCRIPT_DIR, 'templates/cpp_mo class GeneralInfo(): def __init__(self, type, decl, namespaces): - self.symbol_id, self.namespace, self.classpath, self.classname, self.name = self.parseName(decl[0], namespaces) + self.symbol_id, self.parent_id, self.namespace, self.classpath, self.classname, self.name = self.parseName(decl[0], namespaces) + self.cname = get_cname(self.symbol_id) # parse doxygen comments self.params={} @@ -150,6 +151,9 @@ class GeneralInfo(): returns: (namespace, classpath, classname, name) ''' name = name[name.find(" ")+1:].strip() # remove struct/class/const prefix + parent = name[:name.rfind('.')].strip() + if len(parent) == 0: + parent = None spaceName = "" localName = name # . for namespace in sorted(namespaces, key=len, reverse=True): @@ -159,31 +163,44 @@ class GeneralInfo(): break pieces = localName.split(".") if len(pieces) > 2: # ... - return name, spaceName, ".".join(pieces[:-1]), pieces[-2], pieces[-1] + return name, parent, spaceName, ".".join(pieces[:-1]), pieces[-2], pieces[-1] elif len(pieces) == 2: # . - return name, spaceName, pieces[0], pieces[0], pieces[1] + return name, parent, spaceName, pieces[0], pieces[0], pieces[1] elif len(pieces) == 1: # - return name, spaceName, "", "", pieces[0] + return name, parent, spaceName, "", "", pieces[0] else: - return name, spaceName, "", "" # error?! + return name, parent, spaceName, "", "" # error?! - def fullName(self, isCPP=False): - result = ".".join([self.fullClass(), self.name]) - return result if not isCPP else get_cname(result) + def fullNameOrigin(self): + result = self.symbol_id + return result - def fullClass(self, isCPP=False): + def fullNameJAVA(self): + result = '.'.join([self.fullParentNameJAVA(), self.jname]) + return result + + def fullNameCPP(self): + result = self.cname + return result + + def fullParentNameJAVA(self): result = ".".join([f for f in [self.namespace] + self.classpath.split(".") if len(f)>0]) - return result if not isCPP else get_cname(result) + return result + + def fullParentNameCPP(self): + result = get_cname(self.parent_id) + return result class ConstInfo(GeneralInfo): def __init__(self, decl, addedManually=False, namespaces=[], enumType=None): GeneralInfo.__init__(self, "const", decl, namespaces) - self.cname = get_cname(self.name) self.value = decl[1] self.enumType = enumType self.addedManually = addedManually if self.namespace in namespaces_dict: - self.name = '%s_%s' % (namespaces_dict[self.namespace], self.name) + prefix = namespaces_dict[self.namespace] + if prefix: + self.name = '%s_%s' % (prefix, self.name) def __repr__(self): return Template("CONST $name=$value$manual").substitute(name=self.name, @@ -227,7 +244,6 @@ class ClassPropInfo(): class ClassInfo(GeneralInfo): def __init__(self, decl, namespaces=[]): # [ 'class/struct cname', ': base', [modlist] ] GeneralInfo.__init__(self, "class", decl, namespaces) - self.cname = get_cname(self.name) self.methods = [] self.methods_suffixes = {} self.consts = [] # using a list to save the occurrence order @@ -242,6 +258,18 @@ class ClassInfo(GeneralInfo): for m in decl[2]: if m.startswith("="): self.jname = m[1:] + + if self.classpath: + prefix = self.classpath.replace('.', '_') + self.name = '%s_%s' % (prefix, self.name) + self.jname = '%s_%s' % (prefix, self.jname) + + if self.namespace in namespaces_dict: + prefix = namespaces_dict[self.namespace] + if prefix: + self.name = '%s_%s' % (prefix, self.name) + self.jname = '%s_%s' % (prefix, self.jname) + self.base = '' if decl[1]: #self.base = re.sub(r"\b"+self.jname+r"\b", "", decl[1].replace(":", "")).strip() @@ -358,11 +386,26 @@ class FuncInfo(GeneralInfo): self.isconstructor = self.name == self.classname if "[" in self.name: self.jname = "getelem" - if self.namespace in namespaces_dict: - self.jname = '%s_%s' % (namespaces_dict[self.namespace], self.jname) for m in decl[2]: - if m.startswith("="): + if m.startswith("="): # alias from WRAP_AS self.jname = m[1:] + if self.classpath and self.classname != self.classpath: + prefix = self.classpath.replace('.', '_') + self.classname = prefix #'%s_%s' % (prefix, self.classname) + if self.isconstructor: + self.name = prefix #'%s_%s' % (prefix, self.name) + self.jname = prefix #'%s_%s' % (prefix, self.jname) + + if self.namespace in namespaces_dict: + prefix = namespaces_dict[self.namespace] + if prefix: + if self.classname: + self.classname = '%s_%s' % (prefix, self.classname) + if self.isconstructor: + self.jname = '%s_%s' % (prefix, self.jname) + else: + self.jname = '%s_%s' % (prefix, self.jname) + self.static = ["","static"][ "/S" in decl[2] ] self.ctype = re.sub(r"^CvTermCriteria", "TermCriteria", decl[1] or "") self.args = [] @@ -374,6 +417,12 @@ class FuncInfo(GeneralInfo): arg[3] = arg_fix_map.get('attrib', arg[3]) #fixing arg attrib self.args.append(ArgInfo(arg)) + def fullClassJAVA(self): + return self.fullParentNameJAVA() + + def fullClassCPP(self): + return self.fullParentNameCPP() + def __repr__(self): return Template("FUNC <$ctype $namespace.$classpath.$name $args>").substitute(**self.__dict__) @@ -388,7 +437,8 @@ class JavaWrapperGenerator(object): def clear(self): self.namespaces = ["cv"] - self.classes = { "Mat" : ClassInfo([ 'class Mat', '', [], [] ], self.namespaces) } + classinfo_Mat = ClassInfo([ 'class cv.Mat', '', [], [] ], self.namespaces) + self.classes = { "Mat" : classinfo_Mat } self.module = "" self.Module = "" self.ported_func_list = [] @@ -411,7 +461,7 @@ class JavaWrapperGenerator(object): type_dict.setdefault(name, {}).update( { "j_type" : classinfo.jname, "jn_type" : "long", "jn_args" : (("__int64", ".nativeObj"),), - "jni_name" : "(*("+classinfo.fullName(isCPP=True)+"*)%(n)s_nativeObj)", "jni_type" : "jlong", + "jni_name" : "(*("+classinfo.fullNameCPP()+"*)%(n)s_nativeObj)", "jni_type" : "jlong", "suffix" : "J", "j_import" : "org.opencv.%s.%s" % (self.module, classinfo.jname) } @@ -419,7 +469,7 @@ class JavaWrapperGenerator(object): type_dict.setdefault(name+'*', {}).update( { "j_type" : classinfo.jname, "jn_type" : "long", "jn_args" : (("__int64", ".nativeObj"),), - "jni_name" : "("+classinfo.fullName(isCPP=True)+"*)%(n)s_nativeObj", "jni_type" : "jlong", + "jni_name" : "("+classinfo.fullNameCPP()+"*)%(n)s_nativeObj", "jni_type" : "jlong", "suffix" : "J", "j_import" : "org.opencv.%s.%s" % (self.module, classinfo.jname) } @@ -446,7 +496,7 @@ class JavaWrapperGenerator(object): type_dict.setdefault("Ptr_"+name, {}).update( { "j_type" : classinfo.jname, "jn_type" : "long", "jn_args" : (("__int64", ".getNativeObjAddr()"),), - "jni_name" : "*((Ptr<"+classinfo.fullName(isCPP=True)+">*)%(n)s_nativeObj)", "jni_type" : "jlong", + "jni_name" : "*((Ptr<"+classinfo.fullNameCPP()+">*)%(n)s_nativeObj)", "jni_type" : "jlong", "suffix" : "J", "j_import" : "org.opencv.%s.%s" % (self.module, classinfo.jname) } @@ -489,14 +539,15 @@ class JavaWrapperGenerator(object): def add_func(self, decl): fi = FuncInfo(decl, namespaces=self.namespaces) classname = fi.classname or self.Module + class_symbol_id = classname if self.isWrapped(classname) else fi.classpath.replace('.', '_') #('.'.join([fi.namespace, fi.classpath])[3:]) if classname in class_ignore_list: logging.info('ignored: %s', fi) elif classname in ManualFuncs and fi.jname in ManualFuncs[classname]: logging.info('manual: %s', fi) - elif not self.isWrapped(classname): + elif not self.isWrapped(class_symbol_id): logging.warning('not found: %s', fi) else: - self.getClass(classname).addMethod(fi) + self.getClass(class_symbol_id).addMethod(fi) logging.info('ok: %s', fi) # calc args with def val cnt = len([a for a in fi.args if a.defval]) @@ -521,7 +572,7 @@ class JavaWrapperGenerator(object): # TODO: support UMat versions of declarations (implement UMat-wrapper for Java) parser = hdr_parser.CppHeaderParser(generate_umat_decls=False) - self.add_class( ['class ' + self.Module, '', [], []] ) # [ 'class/struct cname', ':bases', [modlist] [props] ] + self.add_class( ['class cv.' + self.Module, '', [], []] ) # [ 'class/struct cname', ':bases', [modlist] [props] ] # scan the headers and build more descriptive maps of classes, consts, functions includes = [] @@ -582,9 +633,9 @@ class JavaWrapperGenerator(object): report.write("\n%i def args - %i funcs" % (i, self.def_args_hist[i])) return report.getvalue() - def fullTypeName(self, t): + def fullTypeNameCPP(self, t): if self.isWrapped(t): - return self.getClass(t).fullName(isCPP=True) + return self.getClass(t).fullNameCPP() else: return cast_from(t) @@ -897,7 +948,7 @@ class JavaWrapperGenerator(object): default = "" elif not fi.ctype: # c-tor if self.isSmartClass(ci): - ret = "return (jlong)(new Ptr<%(ctype)s>(_retval_));" % { 'ctype': fi.fullClass(isCPP=True) } + ret = "return (jlong)(new Ptr<%(ctype)s>(_retval_));" % { 'ctype': fi.fullClassCPP() } else: ret = "return (jlong) _retval_;" elif "v_type" in type_dict[fi.ctype]: # c-tor @@ -907,9 +958,9 @@ class JavaWrapperGenerator(object): ret = "return env->NewStringUTF(_retval_.c_str());" default = 'return env->NewStringUTF("");' elif self.isWrapped(fi.ctype): # wrapped class: - ret = "return (jlong) new %s(_retval_);" % self.fullTypeName(fi.ctype) + ret = "return (jlong) new %s(_retval_);" % self.fullTypeNameCPP(fi.ctype) elif fi.ctype.startswith('Ptr_'): - c_prologue.append("typedef Ptr<%s> %s;" % (self.fullTypeName(fi.ctype[4:]), fi.ctype)) + c_prologue.append("typedef Ptr<%s> %s;" % (self.fullTypeNameCPP(fi.ctype[4:]), fi.ctype)) ret = "return (jlong)(new %(ctype)s(_retval_));" % { 'ctype':fi.ctype } elif self.isWrapped(ret_type): # pointer to wrapped class: ret = "return (jlong) _retval_;" @@ -924,12 +975,12 @@ class JavaWrapperGenerator(object): else: name = prop_name + ";//" - cvname = fi.fullName(isCPP=True) - retval = self.fullTypeName(fi.ctype) + " _retval_ = " if ret else "return " + cvname = fi.fullNameCPP() + retval = self.fullTypeNameCPP(fi.ctype) + " _retval_ = " if ret else "return " if fi.ctype == "void": retval = "" elif fi.ctype == "String": - retval = "cv::" + self.fullTypeName(fi.ctype) + " _retval_ = " + retval = "cv::" + self.fullTypeNameCPP(fi.ctype) + " _retval_ = " elif fi.ctype == "string": retval = "std::string _retval_ = " elif "v_type" in type_dict[fi.ctype]: # vector is returned @@ -945,18 +996,18 @@ class JavaWrapperGenerator(object): if fi.classname: if not fi.ctype: # c-tor if self.isSmartClass(ci): - retval = self.smartWrap(ci, fi.fullClass(isCPP=True)) + " _retval_ = " - cvname = "makePtr<" + fi.fullClass(isCPP=True) +">" + retval = self.smartWrap(ci, fi.fullClassCPP()) + " _retval_ = " + cvname = "makePtr<" + fi.fullClassCPP() +">" else: - retval = fi.fullClass(isCPP=True) + "* _retval_ = " - cvname = "new " + fi.fullClass(isCPP=True) + retval = fi.fullClassCPP() + "* _retval_ = " + cvname = "new " + fi.fullClassCPP() elif fi.static: - cvname = fi.fullName(isCPP=True) + cvname = fi.fullNameCPP() else: cvname = ("me->" if not self.isSmartClass(ci) else "(*me)->") + name c_prologue.append( "%(cls)s* me = (%(cls)s*) self; //TODO: check for NULL" - % { "cls" : self.smartWrap(ci, fi.fullClass(isCPP=True))} + % { "cls" : self.smartWrap(ci, fi.fullClassCPP())} ) cvargs = [] for a in args: @@ -981,13 +1032,12 @@ class JavaWrapperGenerator(object): clazz = ci.jname cpp_code.write ( Template( """ -${namespace} - JNIEXPORT $rtype JNICALL Java_org_opencv_${module}_${clazz}_$fname ($argst); JNIEXPORT $rtype JNICALL Java_org_opencv_${module}_${clazz}_$fname ($args) { + ${namespace} static const char method_name[] = "$module::$fname()"; try { LOGD("%s", method_name);$prologue @@ -1014,7 +1064,7 @@ JNIEXPORT $rtype JNICALL Java_org_opencv_${module}_${clazz}_$fname cvargs = " " + ", ".join(cvargs) + " " if cvargs else "", default = "\n " + default if default else "", retval = retval, - namespace = ('using namespace ' + ci.namespace.replace('.', '::') + ';') if ci.namespace else '' + namespace = ('using namespace ' + ci.namespace.replace('.', '::') + ';') if ci.namespace and ci.namespace != 'cv' else '' ) ) # adding method signature to dictionary @@ -1081,13 +1131,14 @@ JNIEXPORT $rtype JNICALL Java_org_opencv_${module}_${clazz}_$fname self.gen_func(ci, fi) # props for pi in ci.props: + basename = ci.fullNameOrigin() # getter - getter_name = ci.fullName() + ".get_" + pi.name + getter_name = basename + ".get_" + pi.name fi = FuncInfo( [getter_name, pi.ctype, [], []], self.namespaces ) # [ funcname, return_ctype, [modifiers], [args] ] self.gen_func(ci, fi, pi.name) if pi.rw: #setter - setter_name = ci.fullName() + ".set_" + pi.name + setter_name = basename + ".set_" + pi.name fi = FuncInfo( [ setter_name, "void", [], [ [pi.ctype, pi.name, "", [], ""] ] ], self.namespaces) self.gen_func(ci, fi, pi.name) @@ -1131,7 +1182,7 @@ JNIEXPORT void JNICALL Java_org_opencv_%(module)s_%(j_cls)s_delete delete (%(cls)s*) self; } -""" % {"module" : module.replace('_', '_1'), "cls" : self.smartWrap(ci, ci.fullName(isCPP=True)), "j_cls" : ci.jname.replace('_', '_1')} +""" % {"module" : module.replace('_', '_1'), "cls" : self.smartWrap(ci, ci.fullNameCPP()), "j_cls" : ci.jname.replace('_', '_1')} ) def getClass(self, classname):