From 28d410cecff7a6fbeac3f1aba3ecc78248671829 Mon Sep 17 00:00:00 2001 From: utibenkei Date: Wed, 20 Aug 2025 21:06:33 +0900 Subject: [PATCH] Merge pull request #27567 from utibenkei:fix-java-wrapper-missing-vec4i Enable Java wrapper generation for Vec4i #27567 Fixes an issue where Java wrapper generation skips methods using Vec4i. Related PR in opencv_contrib: https://github.com/opencv/opencv_contrib/pull/3988 The root cause was the absence of Vec4i in gen_java.json, which led to important methods such as aruco.drawCharucoDiamond() and ximgproc.HoughPoint2Line() being omitted from the Java bindings. This PR includes the following changes: - Added Vec4i definition to gen_java.json - Updated gen_java.py to handle jintArray-based types properly - ~~Also adjusted jn_args and jni_var for Vec2d and Vec3d to ensure correct JNI behavior~~ The modified Java wrapper generator successfully builds and includes the expected methods using Vec4i. ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [ ] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake --- modules/core/misc/java/gen_dict.json | 25 ++++++++++++++++++++++ modules/java/generator/gen_java.py | 31 ++++++++++++++++++++++++---- 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/modules/core/misc/java/gen_dict.json b/modules/core/misc/java/gen_dict.json index d1267408da..924318c30e 100644 --- a/modules/core/misc/java/gen_dict.json +++ b/modules/core/misc/java/gen_dict.json @@ -648,6 +648,31 @@ "jni_var": "Vec3d %(n)s(%(n)s_val0, %(n)s_val1, %(n)s_val2)", "suffix": "DDD" }, + "Vec4i": { + "j_type": "int[]", + "jn_args": [ + [ + "int", + ".val[0]" + ], + [ + "int", + ".val[1]" + ], + [ + "int", + ".val[2]" + ], + [ + "int", + ".val[3]" + ] + ], + "jn_type": "int[]", + "jni_type": "jintArray", + "jni_var": "Vec4i %(n)s(%(n)s_val0, %(n)s_val1, %(n)s_val2, %(n)s_val3)", + "suffix": "IIII" + }, "c_string": { "j_type": "String", "jn_type": "String", diff --git a/modules/java/generator/gen_java.py b/modules/java/generator/gen_java.py index 797863249d..0885969277 100755 --- a/modules/java/generator/gen_java.py +++ b/modules/java/generator/gen_java.py @@ -743,6 +743,13 @@ class JavaWrapperGenerator(object): "jdouble _tmp_retval_[%(cnt)i] = {%(args)s}; " + "env->SetDoubleArrayRegion(_da_retval_, 0, %(cnt)i, _tmp_retval_);") % { "cnt" : len(fields), "args" : ", ".join(["(jdouble)_retval_" + f[1] for f in fields]) } ) + elif type_dict[fi.ctype]["jni_type"] == "jintArray": + fields = type_dict[fi.ctype]["jn_args"] + c_epilogue.append( + ("jintArray _ia_retval_ = env->NewIntArray(%(cnt)i); " + + "jint _tmp_retval_[%(cnt)i] = {%(args)s}; " + + "env->SetIntArrayRegion(_ia_retval_, 0, %(cnt)i, _tmp_retval_);") % + { "cnt" : len(fields), "args" : ", ".join(["(jint)_retval_" + f[1] for f in fields]) } ) if fi.classname and fi.ctype and not fi.static: # non-static class method except c-tor # adding 'self' jn_args.append ( ArgInfo([ "__int64", "nativeObj", "", [], "" ]) ) @@ -790,7 +797,14 @@ class JavaWrapperGenerator(object): fields = type_dict[a.ctype].get("jn_args", ((a.ctype, ""),)) if "I" in a.out or not a.out or self.isWrapped(a.ctype): # input arg, pass by primitive fields for f in fields: - jn_args.append ( ArgInfo([ f[0], a.name + f[1], "", [], "" ]) ) + # Use array access format for Java code when jn_type is array type + if type_dict[a.ctype].get("jn_type", "").endswith("[]"): + # For Java code: convert .val[0] format to [0] format + jn_args.append ( ArgInfo([ f[0], a.name + f[1].replace(".val[", "["), "", [], "" ]) ) + else: + # For non-array types, use conventional format + jn_args.append ( ArgInfo([ f[0], a.name + f[1], "", [], "" ]) ) + # For C++ code: use conventional format as is jni_args.append( ArgInfo([ f[0], a.name + normalize_field_name(f[1]), "", [], "" ]) ) if "O" in a.out and not self.isWrapped(a.ctype): # out arg, pass as double[] jn_args.append ( ArgInfo([ "double[]", "%s_out" % a.name, "", [], "" ]) ) @@ -805,9 +819,16 @@ class JavaWrapperGenerator(object): set_vals = [] i = 0 for f in fields: - set_vals.append( "%(n)s%(f)s = %(t)s%(n)s_out[%(i)i]" % - {"n" : a.name, "t": ("("+type_dict[f[0]]["j_type"]+")", "")[f[0]=="double"], "f" : f[1], "i" : i} - ) + # Use array access format for Java code when jn_type is array type + if type_dict[a.ctype].get("jn_type", "").endswith("[]"): + # For Java code: convert .val[0] format to [0] format + set_vals.append( "%(n)s%(f)s = %(t)s%(n)s_out[%(i)i]" % + {"n" : a.name, "t": ("("+type_dict[f[0]]["j_type"]+")", "")[f[0]=="double"], "f" : f[1].replace(".val[", "["), "i" : i} + ) + else: + set_vals.append( "%(n)s%(f)s = %(t)s%(n)s_out[%(i)i]" % + {"n" : a.name, "t": ("("+type_dict[f[0]]["j_type"]+")", "")[f[0]=="double"], "f" : f[1], "i" : i} + ) i += 1 j_epilogue.append( "if("+a.name+"!=null){ " + "; ".join(set_vals) + "; } ") @@ -1002,6 +1023,8 @@ class JavaWrapperGenerator(object): ret = "return (jlong) _retval_;" elif type_dict[fi.ctype]["jni_type"] == "jdoubleArray": ret = "return _da_retval_;" + elif type_dict[fi.ctype]["jni_type"] == "jintArray": + ret = "return _ia_retval_;" elif "jni_var" in type_dict[ret_type]: c_epilogue.append(type_dict[ret_type]["jni_var"] % {"n" : '_retval_'}) ret = f"return {type_dict[ret_type]['jni_name'] % {'n' : '_retval_'}};"