Java API generator: refactored manual const and funcs handling, collected real 'import' needs for java classes (to eliminate eclipse warnings in java classes)

pull/13383/head
Andrey Pavlenko 14 years ago
parent a28112472c
commit eb5e22dd74
  1. 737
      modules/java/gen_java.py

@ -8,30 +8,9 @@ except:
class_ignore_list = ( class_ignore_list = (
#core #core
"FileNode", "FileNode", "FileStorage",
"FileStorage",
#highgui #highgui
"VideoWriter", "VideoWriter", "VideoCapture",
"VideoCapture",
)
func_ignore_list = (
#core
"checkHardwareSupport",
"setUseOptimized",
"useOptimized",
"vconcat",
#highgui
"namedWindow",
"destroyWindow",
"destroyAllWindows",
"startWindowThread",
"setWindowProperty",
"getWindowProperty",
"getTrackbarPos",
"setTrackbarPos",
"imshow",
"waitKey",
) )
const_ignore_list = ( const_ignore_list = (
@ -109,6 +88,64 @@ const_ignore_list = (
"CV_FLOODFILL_.+", "CV_FLOODFILL_.+",
) )
# { Module : { public : [[name, val],...], private : [[]...] } }
missing_consts = \
{
'Core' :
{
'private' :
(
('CV_8U', 0 ), ('CV_8S', 1 ),
('CV_16U', 2 ), ('CV_16S', 3 ),
('CV_32S', 4 ),
('CV_32F', 5 ), ('CV_64F', 6 ),
('CV_USRTYPE1', 7 ),
) # private
}, # Core
"Imgproc":
{
'private' :
(
('IPL_BORDER_CONSTANT', 0 ),
('IPL_BORDER_REPLICATE', 1 ),
('IPL_BORDER_REFLECT', 2 ),
('IPL_BORDER_WRAP', 3 ),
('IPL_BORDER_REFLECT_101', 4 ),
('IPL_BORDER_TRANSPARENT', 5 ),
) # private
}, # Imgproc
"Calib3d":
{
'public' :
(
('CV_LMEDS', 4),
('CV_RANSAC', 8),
('CV_FM_LMEDS', 'CV_LMEDS'),
('CV_FM_RANSAC','CV_RANSAC'),
('CV_FM_7POINT', 1),
('CV_FM_8POINT', 2),
('CV_CALIB_USE_INTRINSIC_GUESS', 1),
('CV_CALIB_FIX_ASPECT_RATIO', 2),
('CV_CALIB_FIX_PRINCIPAL_POINT', 4),
('CV_CALIB_ZERO_TANGENT_DIST', 8),
('CV_CALIB_FIX_FOCAL_LENGTH', 16),
('CV_CALIB_FIX_K1', 32),
('CV_CALIB_FIX_K2', 64),
('CV_CALIB_FIX_K3', 128),
('CV_CALIB_FIX_K4', 2048),
('CV_CALIB_FIX_K5', 4096),
('CV_CALIB_FIX_K6', 8192),
('CV_CALIB_RATIONAL_MODEL', 16384),
('CV_CALIB_FIX_INTRINSIC', 256),
('CV_CALIB_SAME_FOCAL_LENGTH', 512),
('CV_CALIB_ZERO_DISPARITY', 1024),
) # public
}, # Calib3d
}
# c_type : { java/jni correspondence } # c_type : { java/jni correspondence }
type_dict = { type_dict = {
@ -126,6 +163,9 @@ type_dict = {
"__int64" : { "j_type" : "long", "jn_type" : "long", "jni_type" : "jlong", "suffix" : "J" }, "__int64" : { "j_type" : "long", "jn_type" : "long", "jni_type" : "jlong", "suffix" : "J" },
"int64" : { "j_type" : "long", "jn_type" : "long", "jni_type" : "jlong", "suffix" : "J" }, "int64" : { "j_type" : "long", "jn_type" : "long", "jni_type" : "jlong", "suffix" : "J" },
"double[]": { "j_type" : "double[]", "jn_type" : "double[]", "jni_type" : "jdoubleArray", "suffix" : "_3D" }, "double[]": { "j_type" : "double[]", "jn_type" : "double[]", "jni_type" : "jdoubleArray", "suffix" : "_3D" },
# "complex" : { j_type : "?", jn_args : (("", ""),), jn_name : "", jni_var : "", jni_name : "", "suffix" : "?" },
"vector_Point": { "j_type" : "java.util.List<Point>", "jn_type" : "long", "jni_type" : "jlong", "jni_var" : "vector<Point> %(n)s", "suffix" : "J" }, "vector_Point": { "j_type" : "java.util.List<Point>", "jn_type" : "long", "jni_type" : "jlong", "jni_var" : "vector<Point> %(n)s", "suffix" : "J" },
"vector_Mat" : { "j_type" : "java.util.List<Mat>", "jn_type" : "long", "jni_type" : "jlong", "jni_var" : "vector<Mat> %(n)s", "suffix" : "J" }, "vector_Mat" : { "j_type" : "java.util.List<Mat>", "jn_type" : "long", "jni_type" : "jlong", "jni_var" : "vector<Mat> %(n)s", "suffix" : "J" },
"vector_KeyPoint" : { "j_type" : "java.util.List<KeyPoint>", "jn_type" : "long", "jni_type" : "jlong", "jni_var" : "vector<KeyPoint> %(n)s", "suffix" : "J" }, "vector_KeyPoint" : { "j_type" : "java.util.List<KeyPoint>", "jn_type" : "long", "jni_type" : "jlong", "jni_var" : "vector<KeyPoint> %(n)s", "suffix" : "J" },
@ -134,7 +174,7 @@ type_dict = {
"vector_int" : { "j_type" : "java.util.List<Integer>", "jn_type" : "long", "jni_type" : "jlong", "jni_var" : "vector<int> %(n)s", "suffix" : "J" }, "vector_int" : { "j_type" : "java.util.List<Integer>", "jn_type" : "long", "jni_type" : "jlong", "jni_var" : "vector<int> %(n)s", "suffix" : "J" },
"vector_float" : { "j_type" : "java.util.List<Float>", "jn_type" : "long", "jni_type" : "jlong", "jni_var" : "vector<float> %(n)s", "suffix" : "J" }, "vector_float" : { "j_type" : "java.util.List<Float>", "jn_type" : "long", "jni_type" : "jlong", "jni_var" : "vector<float> %(n)s", "suffix" : "J" },
"vector_double" : { "j_type" : "java.util.List<Double>", "jn_type" : "long", "jni_type" : "jlong", "jni_var" : "vector<double> %(n)s", "suffix" : "J" }, "vector_double" : { "j_type" : "java.util.List<Double>", "jn_type" : "long", "jni_type" : "jlong", "jni_var" : "vector<double> %(n)s", "suffix" : "J" },
# "complex" : { j_type : "?", jn_args : (("", ""),), jn_name : "", jni_var : "", jni_name : "", "suffix" : "?" },
"Mat" : { "j_type" : "Mat", "jn_type" : "long", "jn_args" : (("__int64", ".nativeObj"),), "Mat" : { "j_type" : "Mat", "jn_type" : "long", "jn_args" : (("__int64", ".nativeObj"),),
"jni_var" : "Mat& %(n)s = *((Mat*)%(n)s_nativeObj)", "jni_var" : "Mat& %(n)s = *((Mat*)%(n)s_nativeObj)",
"jni_type" : "jlong", #"jni_name" : "*%(n)s", "jni_type" : "jlong", #"jni_name" : "*%(n)s",
@ -200,12 +240,204 @@ type_dict = {
} }
setManualFunctions=set(['minMaxLoc', 'getTextSize']) # { Module : { func : {j_code, jn_code, cpp_code} } }
ManualFuncs = {
'Core' :
{
'minMaxLoc' : {
'j_code' : """
// manual port
public static class MinMaxLocResult {
public double minVal;
public double maxVal;
public Point minLoc;
public Point maxLoc;
public MinMaxLocResult() {
minVal=0; maxVal=0;
minLoc=new Point();
maxLoc=new Point();
}
}
// C++: minMaxLoc(Mat src, double* minVal, double* maxVal=0, Point* minLoc=0, Point* maxLoc=0, InputArray mask=noArray())
//javadoc: minMaxLoc(src, mask)
public static MinMaxLocResult minMaxLoc(Mat src, Mat mask) {
MinMaxLocResult res = new MinMaxLocResult();
long maskNativeObj=0;
if (mask != null) {
maskNativeObj=mask.nativeObj;
}
double resarr[] = n_minMaxLocManual(src.nativeObj, maskNativeObj);
res.minVal=resarr[0];
res.maxVal=resarr[1];
res.minLoc.x=resarr[2];
res.minLoc.y=resarr[3];
res.maxLoc.x=resarr[4];
res.maxLoc.y=resarr[5];
return res;
}
//javadoc: minMaxLoc(src)
public static MinMaxLocResult minMaxLoc(Mat src) {
return minMaxLoc(src, null);
}
""",
'jn_code' :
""" private static native double[] n_minMaxLocManual(long src_nativeObj, long mask_nativeObj);\n""",
'cpp_code' :
"""
// C++: minMaxLoc(Mat src, double* minVal, double* maxVal=0, Point* minLoc=0, Point* maxLoc=0, InputArray mask=noArray())
JNIEXPORT jdoubleArray JNICALL Java_org_opencv_core_Core_n_1minMaxLocManual
(JNIEnv* env, jclass cls, jlong src_nativeObj, jlong mask_nativeObj)
{
try {
LOGD("Core::n_1minMaxLoc()");
jdoubleArray result;
result = env->NewDoubleArray(6);
if (result == NULL) {
return NULL; /* out of memory error thrown */
}
Mat& src = *((Mat*)src_nativeObj);
double minVal, maxVal;
Point minLoc, maxLoc;
if (mask_nativeObj != 0) {
Mat& mask = *((Mat*)mask_nativeObj);
minMaxLoc(src, &minVal, &maxVal, &minLoc, &maxLoc, mask);
} else {
minMaxLoc(src, &minVal, &maxVal, &minLoc, &maxLoc);
}
jdouble fill[6];
fill[0]=minVal;
fill[1]=maxVal;
fill[2]=minLoc.x;
fill[3]=minLoc.y;
fill[4]=maxLoc.x;
fill[5]=maxLoc.y;
env->SetDoubleArrayRegion(result, 0, 6, fill);
return result;
} catch(cv::Exception e) {
LOGD("Core::n_1minMaxLoc() catched cv::Exception: %s", e.what());
jclass je = env->FindClass("org/opencv/core/CvException");
if(!je) je = env->FindClass("java/lang/Exception");
env->ThrowNew(je, e.what());
return NULL;
} catch (...) {
LOGD("Core::n_1minMaxLoc() catched unknown exception (...)");
jclass je = env->FindClass("java/lang/Exception");
env->ThrowNew(je, "Unknown exception in JNI code {core::minMaxLoc()}");
return NULL;
}
}
""",
}, # minMaxLoc
'getTextSize' :
{
'j_code' :
"""
// C++: Size getTextSize(const string& text, int fontFace, double fontScale, int thickness, int* baseLine);
//javadoc:getTextSize(text, fontFace, fontScale, thickness, baseLine)
public static Size getTextSize(String text, int fontFace, double fontScale, int thickness, int[] baseLine) {
if(baseLine != null && baseLine.length != 1)
throw new java.lang.IllegalArgumentException("'baseLine' must be 'int[1]' or 'null'.");
Size retVal = new Size(n_getTextSize(text, fontFace, fontScale, thickness, baseLine));
return retVal;
}
""",
'jn_code' :
""" private static native double[] n_getTextSize(String text, int fontFace, double fontScale, int thickness, int[] baseLine);\n""",
'cpp_code' :
"""
// C++: Size getTextSize(const string& text, int fontFace, double fontScale, int thickness, int* baseLine);
JNIEXPORT jdoubleArray JNICALL Java_org_opencv_core_Core_n_1getTextSize
(JNIEnv* env, jclass cls, jstring text, jint fontFace, jdouble fontScale, jint thickness, jintArray baseLine)
{
try {
LOGD("Core::n_1getTextSize()");
jdoubleArray result;
result = env->NewDoubleArray(2);
if (result == NULL) {
return NULL; /* out of memory error thrown */
}
const char* utf_text = env->GetStringUTFChars(text, 0);
std::string n_text( utf_text ? utf_text : "" );
env->ReleaseStringUTFChars(text, utf_text);
int _baseLine;
int* pbaseLine = 0;
if (baseLine != NULL)
pbaseLine = &_baseLine;
cv::Size rsize = cv::getTextSize(n_text, (int)fontFace, (double)fontScale, (int)thickness, pbaseLine);
jdouble fill[2];
fill[0]=rsize.width;
fill[1]=rsize.height;
env->SetDoubleArrayRegion(result, 0, 2, fill);
if (baseLine != NULL)
env->SetIntArrayRegion(baseLine, 0, 1, pbaseLine);
return result;
} catch(cv::Exception e) {
LOGD("Core::n_1getTextSize() catched cv::Exception: %s", e.what());
jclass je = env->FindClass("org/opencv/core/CvException");
if(!je) je = env->FindClass("java/lang/Exception");
env->ThrowNew(je, e.what());
return NULL;
} catch (...) {
LOGD("Core::n_1getTextSize() catched unknown exception (...)");
jclass je = env->FindClass("java/lang/Exception");
env->ThrowNew(je, "Unknown exception in JNI code {core::getTextSize()}");
return NULL;
}
}
""",
}, # getTextSize
"checkHardwareSupport" : {'j_code' : '', 'jn_code' : '', 'cpp_code' : '' },
"setUseOptimized" : {'j_code' : '', 'jn_code' : '', 'cpp_code' : '' },
"useOptimized" : {'j_code' : '', 'jn_code' : '', 'cpp_code' : '' },
"vconcat" : {'j_code' : '', 'jn_code' : '', 'cpp_code' : '' },
}, # Core
'Highgui' :
{
"namedWindow" : {'j_code' : '', 'jn_code' : '', 'cpp_code' : '' },
"destroyWindow" : {'j_code' : '', 'jn_code' : '', 'cpp_code' : '' },
"destroyAllWindows" : {'j_code' : '', 'jn_code' : '', 'cpp_code' : '' },
"startWindowThread" : {'j_code' : '', 'jn_code' : '', 'cpp_code' : '' },
"setWindowProperty" : {'j_code' : '', 'jn_code' : '', 'cpp_code' : '' },
"getWindowProperty" : {'j_code' : '', 'jn_code' : '', 'cpp_code' : '' },
"getTrackbarPos" : {'j_code' : '', 'jn_code' : '', 'cpp_code' : '' },
"setTrackbarPos" : {'j_code' : '', 'jn_code' : '', 'cpp_code' : '' },
"imshow" : {'j_code' : '', 'jn_code' : '', 'cpp_code' : '' },
"waitKey" : {'j_code' : '', 'jn_code' : '', 'cpp_code' : '' },
}, # Highgui
}
class ConstInfo(object): class ConstInfo(object):
def __init__(self, cname, name, val): def __init__(self, cname, name, val):
self.cname = cname self.cname = cname
self.name = re.sub(r"^Cv", "", name) self.name = re.sub(r"^Cv", "", name)
self.value = val self.value = val
@ -223,6 +455,8 @@ class ClassInfo(object):
self.cname =self.cname.replace(".", "::") self.cname =self.cname.replace(".", "::")
self.methods = {} self.methods = {}
self.consts = [] # using a list to save the occurence order self.consts = [] # using a list to save the occurence order
self.private_consts = []
self.imports = set()
self.props= [] self.props= []
for m in decl[2]: for m in decl[2]:
if m.startswith("="): if m.startswith("="):
@ -264,8 +498,6 @@ class FuncInfo(object):
self.jname = m[1:] self.jname = m[1:]
self.jn_name = "n_" + self.jname self.jn_name = "n_" + self.jname
self.jni_name= re.sub(r"_", "_1", self.jn_name) self.jni_name= re.sub(r"_", "_1", self.jn_name)
## if self.classname:
## self.jni_name = "00024" + self.classname + "_" + self.jni_name
self.static = ["","static"][ "/S" in decl[2] ] self.static = ["","static"][ "/S" in decl[2] ]
self.ctype = decl[1] or "" self.ctype = decl[1] or ""
self.args = [] self.args = []
@ -298,8 +530,6 @@ class JavaWrapperGenerator(object):
def clear(self): def clear(self):
self.classes = { "Mat" : ClassInfo([ 'class Mat', [], [] ]) } self.classes = { "Mat" : ClassInfo([ 'class Mat', [], [] ]) }
self.funcs = {}
self.consts = [] # using a list to save the occurence order
self.module = "" self.module = ""
self.Module = "" self.Module = ""
self.java_code= {} # { class : {j_code, jn_code} } self.java_code= {} # { class : {j_code, jn_code} }
@ -357,6 +587,15 @@ public class %s {
"jni_name" : "(*("+classinfo.name+"*)%(n)s_nativeObj)", "jni_type" : "jlong", "jni_name" : "(*("+classinfo.name+"*)%(n)s_nativeObj)", "jni_type" : "jlong",
"suffix" : "J" } "suffix" : "J" }
# missing_consts { Module : { public : [[name, val],...], private : [[]...] } }
if classinfo.name in missing_consts:
if 'private' in missing_consts[classinfo.name]:
for (name, val) in missing_consts[classinfo.name]['private']:
classinfo.private_consts.append( ConstInfo(name, name, val) )
if 'public' in missing_consts[classinfo.name]:
for (name, val) in missing_consts[classinfo.name]['public']:
classinfo.consts.append( ConstInfo(name, name, val) )
# class props # class props
for p in decl[3]: for p in decl[3]:
if "vector" not in p[0]: if "vector" not in p[0]:
@ -368,24 +607,24 @@ public class %s {
def add_const(self, decl): # [ "const cname", val, [], [] ] def add_const(self, decl): # [ "const cname", val, [], [] ]
consts = self.consts
name = decl[0].replace("const ", "").strip() name = decl[0].replace("const ", "").strip()
name = re.sub(r"^cv\.", "", name) name = re.sub(r"^cv\.", "", name)
cname = name.replace(".", "::") cname = name.replace(".", "::")
for c in const_ignore_list: for c in const_ignore_list:
if re.match(c, name): if re.match(c, name):
return return
# check if it's a class member # class member?
dpos = name.rfind(".") dpos = name.rfind(".")
if dpos >= 0: if dpos >= 0:
classname = name[:dpos] classname = name[:dpos]
name = name[dpos+1:] name = name[dpos+1:]
if classname in self.classes: else:
consts = self.classes[classname].consts classname = self.Module
else: if classname not in self.classes:
# this class isn't wrapped # this class isn't wrapped
# skipping this const # skipping this const
return return
consts = self.classes[classname].consts
constinfo = ConstInfo(cname, name, decl[1]) constinfo = ConstInfo(cname, name, decl[1])
# checking duplication # checking duplication
for c in consts: for c in consts:
@ -397,20 +636,16 @@ public class %s {
def add_func(self, decl): def add_func(self, decl):
ffi = FuncFamilyInfo(decl) ffi = FuncFamilyInfo(decl)
if ffi.jname in setManualFunctions : classname = ffi.funcs[0].classname or self.Module
print "Found function, which is ported manually: " + ffi.jname if classname in class_ignore_list:
return None
func_map = self.funcs
classname = ffi.funcs[0].classname
if classname in class_ignore_list or ffi.jname in func_ignore_list:
return return
if classname: if classname in ManualFuncs and ffi.jname in ManualFuncs[classname]:
if classname in self.classes: return
func_map = self.classes[classname].methods if classname not in self.classes:
else: print "Generator error: the class %s for method %s is missing" % \
print "Generator error: the class %s for method %s is missing" % \ (classname, ffi.jname)
(classname, ffi.jname) sys.exit(-1)
sys.exit(-1) func_map = self.classes[classname].methods
if ffi.jname in func_map: if ffi.jname in func_map:
func_map[ffi.jname].add_func(ffi.funcs[0]) func_map[ffi.jname].add_func(ffi.funcs[0])
else: else:
@ -427,117 +662,21 @@ public class %s {
self.Module = module.capitalize() self.Module = module.capitalize()
parser = hdr_parser.CppHeaderParser() parser = hdr_parser.CppHeaderParser()
# step 1: scan the headers and build more descriptive maps of classes, consts, functions self.add_class( ['class ' + self.Module, [], [], []] ) # [ 'class/struct cname', [bases], [modlist] [props] ]
# scan the headers and build more descriptive maps of classes, consts, functions
for hdr in srcfiles: for hdr in srcfiles:
decls = parser.parse(hdr) decls = parser.parse(hdr)
for decl in decls: for decl in decls:
name = decl[0] name = decl[0]
if name.startswith("struct") or name.startswith("class"): if name.startswith("struct") or name.startswith("class"):
self.add_class(decl) self.add_class(decl)
pass
elif name.startswith("const"): elif name.startswith("const"):
self.add_const(decl) self.add_const(decl)
else: # function else: # function
self.add_func(decl) self.add_func(decl)
pass
self.add_class_code_stream(self.Module)
self.cpp_code = StringIO() self.cpp_code = StringIO()
# java code
if module == "core":
self.java_code[self.Module]["j_code"].write(\
"""
private static final int
CV_8U = 0, CV_8S = 1, CV_16U = 2, CV_16S = 3, CV_32S = 4, CV_32F = 5, CV_64F = 6, CV_USRTYPE1 = 7;
//Manual ported functions
// C++: minMaxLoc(Mat src, double* minVal, double* maxVal=0, Point* minLoc=0, Point* maxLoc=0, InputArray mask=noArray())
//javadoc: minMaxLoc
public static class MinMaxLocResult {
public double minVal;
public double maxVal;
public Point minLoc;
public Point maxLoc;
public MinMaxLocResult() {
minVal=0; maxVal=0;
minLoc=new Point();
maxLoc=new Point();
}
}
public static MinMaxLocResult minMaxLoc(Mat src, Mat mask) {
MinMaxLocResult res = new MinMaxLocResult();
long maskNativeObj=0;
if (mask != null) {
maskNativeObj=mask.nativeObj;
}
double resarr[] = n_minMaxLocManual(src.nativeObj, maskNativeObj);
res.minVal=resarr[0];
res.maxVal=resarr[1];
res.minLoc.x=resarr[2];
res.minLoc.y=resarr[3];
res.maxLoc.x=resarr[4];
res.maxLoc.y=resarr[5];
return res;
}
public static MinMaxLocResult minMaxLoc(Mat src) {
return minMaxLoc(src, null);
}
private static native double[] n_minMaxLocManual(long src_nativeObj, long mask_nativeObj);
//javadoc:getTextSize(text, fontFace, fontScale, thickness, baseLine)
public static Size getTextSize(String text, int fontFace, double fontScale, int thickness, int[] baseLine) {
assert(baseLine == null || baseLine.length == 1);
Size retVal = new Size(n_getTextSize(text, fontFace, fontScale, thickness, baseLine));
return retVal;
}
private static native double[] n_getTextSize(String text, int fontFace, double fontScale, int thickness, int[] baseLine);
""" )
if module == "imgproc":
self.java_code[self.Module]["j_code"].write(\
"""
private static final int
IPL_BORDER_CONSTANT = 0, IPL_BORDER_REPLICATE = 1, IPL_BORDER_REFLECT = 2,
IPL_BORDER_WRAP = 3, IPL_BORDER_REFLECT_101 = 4, IPL_BORDER_TRANSPARENT = 5;
""" )
if module == "calib3d":
self.java_code[self.Module]["j_code"].write(\
"""
public static final int
CV_LMEDS = 4,
CV_RANSAC = 8,
CV_FM_LMEDS = CV_LMEDS,
CV_FM_RANSAC = CV_RANSAC;
public static final int
CV_FM_7POINT = 1,
CV_FM_8POINT = 2;
public static final int
CV_CALIB_USE_INTRINSIC_GUESS = 1,
CV_CALIB_FIX_ASPECT_RATIO = 2,
CV_CALIB_FIX_PRINCIPAL_POINT = 4,
CV_CALIB_ZERO_TANGENT_DIST = 8,
CV_CALIB_FIX_FOCAL_LENGTH = 16,
CV_CALIB_FIX_K1 = 32,
CV_CALIB_FIX_K2 = 64,
CV_CALIB_FIX_K3 = 128,
CV_CALIB_FIX_K4 = 2048,
CV_CALIB_FIX_K5 = 4096,
CV_CALIB_FIX_K6 = 8192,
CV_CALIB_RATIONAL_MODEL = 16384,
CV_CALIB_FIX_INTRINSIC = 256,
CV_CALIB_SAME_FOCAL_LENGTH = 512,
CV_CALIB_ZERO_DISPARITY = 1024;
""" )
# cpp module header
self.cpp_code.write(""" self.cpp_code.write("""
// //
// This file is auto-generated, please don't edit! // This file is auto-generated, please don't edit!
@ -545,129 +684,30 @@ public class %s {
#include <jni.h> #include <jni.h>
#include "utils.h"
#ifdef DEBUG #ifdef DEBUG
#include <android/log.h> #include <android/log.h>
#define MODULE_LOG_TAG "OpenCV.%s" #define MODULE_LOG_TAG "OpenCV.%(m)s"
#define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, MODULE_LOG_TAG, __VA_ARGS__)) #define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, MODULE_LOG_TAG, __VA_ARGS__))
#else //DEBUG #else //DEBUG
#define LOGD(...) #define LOGD(...)
#endif //DEBUG #endif //DEBUG
#include "utils.h" #include "opencv2/%(m)s/%(m)s.hpp"
""" % module)
self.cpp_code.write( "\n".join(['#include "opencv2/%s/%s"' % (module, os.path.basename(f)) \
for f in srcfiles]) )
self.cpp_code.write('\nusing namespace cv;\n')
self.cpp_code.write('\n\nextern "C" {\n\n')
# step 2: generate the code for global constants
self.gen_consts(self.consts, self.java_code[self.Module]["j_code"])
# step 3: generate the code for all the global functions
self.gen_funcs()
# step 4: generate code for the classes
self.gen_classes()
if module == "core":
self.cpp_code.write(\
"""
JNIEXPORT jdoubleArray JNICALL Java_org_opencv_core_Core_n_1minMaxLocManual
(JNIEnv* env, jclass cls, jlong src_nativeObj, jlong mask_nativeObj)
{
try {
LOGD("Core::n_1minMaxLoc()");
jdoubleArray result;
result = env->NewDoubleArray(6);
if (result == NULL) {
return NULL; /* out of memory error thrown */
}
Mat& src = *((Mat*)src_nativeObj);
double minVal, maxVal;
Point minLoc, maxLoc;
if (mask_nativeObj != 0) {
Mat& mask = *((Mat*)mask_nativeObj);
minMaxLoc(src, &minVal, &maxVal, &minLoc, &maxLoc, mask);
} else {
minMaxLoc(src, &minVal, &maxVal, &minLoc, &maxLoc);
}
jdouble fill[6];
fill[0]=minVal;
fill[1]=maxVal;
fill[2]=minLoc.x;
fill[3]=minLoc.y;
fill[4]=maxLoc.x;
fill[5]=maxLoc.y;
env->SetDoubleArrayRegion(result, 0, 6, fill);
return result;
} catch(cv::Exception e) {
LOGD("Core::n_1minMaxLoc() catched cv::Exception: %s", e.what());
jclass je = env->FindClass("org/opencv/core/CvException");
if(!je) je = env->FindClass("java/lang/Exception");
env->ThrowNew(je, e.what());
return NULL;
} catch (...) {
LOGD("Core::n_1minMaxLoc() catched unknown exception (...)");
jclass je = env->FindClass("java/lang/Exception");
env->ThrowNew(je, "Unknown exception in JNI code {core::minMaxLoc()}");
return NULL;
}
}
JNIEXPORT jdoubleArray JNICALL Java_org_opencv_core_Core_n_1getTextSize
(JNIEnv* env, jclass cls, jstring text, jint fontFace, jdouble fontScale, jint thickness, jintArray baseLine)
{
try {
LOGD("Core::n_1getTextSize()");
jdoubleArray result;
result = env->NewDoubleArray(2);
if (result == NULL) {
return NULL; /* out of memory error thrown */
}
const char* utf_text = env->GetStringUTFChars(text, 0);
std::string n_text( utf_text ? utf_text : "" );
env->ReleaseStringUTFChars(text, utf_text);
int _baseLine;
int* pbaseLine = 0;
if (baseLine != NULL)
pbaseLine = &_baseLine;
cv::Size rsize = cv::getTextSize(n_text, (int)fontFace, (double)fontScale, (int)thickness, pbaseLine); using namespace cv;
jdouble fill[2]; extern "C" {
fill[0]=rsize.width;
fill[1]=rsize.height;
env->SetDoubleArrayRegion(result, 0, 2, fill); """ % {'m' : module} )
if (baseLine != NULL) #"\n".join(['#include "opencv2/%s/%s"' % (module, os.path.basename(f)) for f in srcfiles])
env->SetIntArrayRegion(baseLine, 0, 1, pbaseLine);
return result; # generate code for the classes
for name in self.classes.keys():
self.gen_class(name)
} catch(cv::Exception e) {
LOGD("Core::n_1getTextSize() catched cv::Exception: %s", e.what());
jclass je = env->FindClass("org/opencv/core/CvException");
if(!je) je = env->FindClass("java/lang/Exception");
env->ThrowNew(je, e.what());
return NULL;
} catch (...) {
LOGD("Core::n_1getTextSize() catched unknown exception (...)");
jclass je = env->FindClass("java/lang/Exception");
env->ThrowNew(je, "Unknown exception in JNI code {core::getTextSize()}");
return NULL;
}
}
""")
# saving code streams # saving code streams
for cls in self.java_code.keys(): for cls in self.java_code.keys():
self.java_code[cls]["j_code"].write("\n\n%s\n}\n" % self.java_code[cls]["jn_code"].getvalue()) self.java_code[cls]["j_code"].write("\n\n%s\n}\n" % self.java_code[cls]["jn_code"].getvalue())
@ -692,46 +732,33 @@ JNIEXPORT jdoubleArray JNICALL Java_org_opencv_core_Core_n_1getTextSize
def gen_consts(self, consts, code_stream):
if consts:
code_stream.write("""
public static final int
%s;\n\n""" % (",\n"+" "*12).join(["%s = %s" % (c.name, c.value) for c in consts])
)
def gen_func(self, fi, isoverload): def gen_func(self, fi, isoverload):
# // C++: c_decl self.gen_func2(fi, isoverload, "")
# e.g: // C++: void add(Mat src1, Mat src2, Mat dst, Mat mask = Mat(), int dtype = -1)
decl_args = []
for a in fi.args: def gen_func2(self, fi, isoverload, prop_name):
s = a.ctype j_code = self.java_code[fi.classname or self.Module]["j_code"]
if a.pointer: jn_code = self.java_code[fi.classname or self.Module]["jn_code"]
s += "*"
elif a.out:
s += "&"
s += " " + a.name
if a.defval:
s += " = "+a.defval
decl_args.append(s)
c_decl = "%s %s %s(%s)" % ( fi.static, fi.ctype, fi.cname, ", ".join(decl_args) )
#java doc comment
f_name = fi.name
if fi.classname:
f_name = fi.classname + "::" + fi.name
java_doc = "//javadoc: " + f_name + "(%s)" % ", ".join([a.name for a in fi.args])
self.gen_func2(fi, isoverload, c_decl, java_doc, "")
def gen_func2(self, fi, isoverload, c_decl, java_doc, prop_name):
j_code = self.java_code[self.Module]["j_code"]
jn_code = self.java_code[self.Module]["jn_code"]
cpp_code = self.cpp_code cpp_code = self.cpp_code
if fi.classname:
j_code = self.java_code[fi.classname]["j_code"] # c_decl
jn_code = self.java_code[fi.classname]["jn_code"] # e.g: void add(Mat src1, Mat src2, Mat dst, Mat mask = Mat(), int dtype = -1)
if prop_name:
c_decl = "%s %s::%s" % (fi.ctype, fi.classname, prop_name)
else:
decl_args = []
for a in fi.args:
s = a.ctype
if a.pointer:
s += "*"
elif a.out:
s += "&"
s += " " + a.name
if a.defval:
s += " = "+a.defval
decl_args.append(s)
c_decl = "%s %s %s(%s)" % ( fi.static, fi.ctype, fi.cname, ", ".join(decl_args) )
# java comment # java comment
j_code.write( "\n //\n // C++: %s\n //\n\n" % c_decl ) j_code.write( "\n //\n // C++: %s\n //\n\n" % c_decl )
@ -772,7 +799,11 @@ JNIEXPORT jdoubleArray JNICALL Java_org_opencv_core_Core_n_1getTextSize
j_epilogue = [] j_epilogue = []
c_prologue = [] c_prologue = []
c_epilogue = [] c_epilogue = []
if fi.ctype == 'Mat':
self.classes[fi.classname or self.Module].imports.add("org.opencv.core.Mat")
if type_dict[fi.ctype]["jni_type"] == "jdoubleArray": if type_dict[fi.ctype]["jni_type"] == "jdoubleArray":
if "Vec" not in fi.ctype:
self.classes[fi.classname or self.Module].imports.add("org.opencv.core." + type_dict[fi.ctype]["j_type"])
fields = type_dict[fi.ctype]["jn_args"] fields = type_dict[fi.ctype]["jn_args"]
c_epilogue.append( \ c_epilogue.append( \
("jdoubleArray _da_retval_ = env->NewDoubleArray(%(cnt)i); " + ("jdoubleArray _da_retval_ = env->NewDoubleArray(%(cnt)i); " +
@ -788,6 +819,9 @@ JNIEXPORT jdoubleArray JNICALL Java_org_opencv_core_Core_n_1getTextSize
suffix += type_dict[a.ctype].get("suffix") or "" suffix += type_dict[a.ctype].get("suffix") or ""
if "vector" in a.ctype: # pass as Mat if "vector" in a.ctype: # pass as Mat
self.classes[fi.classname or self.Module].imports.add("org.opencv.core.Mat")
self.classes[fi.classname or self.Module].imports.add("org.opencv.core.Utils")
self.classes[fi.classname or self.Module].imports.add("java.util.List")
jn_args.append ( ArgInfo([ "__int64", "%s_mat.nativeObj" % a.name, "", [], "" ]) ) jn_args.append ( ArgInfo([ "__int64", "%s_mat.nativeObj" % a.name, "", [], "" ]) )
jni_args.append ( ArgInfo([ "__int64", "%s_mat_nativeObj" % a.name, "", [], "" ]) ) jni_args.append ( ArgInfo([ "__int64", "%s_mat_nativeObj" % a.name, "", [], "" ]) )
c_prologue.append( type_dict[a.ctype]["jni_var"] % {"n" : a.name} + ";" ) c_prologue.append( type_dict[a.ctype]["jni_var"] % {"n" : a.name} + ";" )
@ -801,7 +835,10 @@ JNIEXPORT jdoubleArray JNICALL Java_org_opencv_core_Core_n_1getTextSize
j_epilogue.append("utils.Mat_to_%(t)s(%(n)s_mat, %(n)s);" % {"t" : a.ctype, "n" : a.name}) j_epilogue.append("utils.Mat_to_%(t)s(%(n)s_mat, %(n)s);" % {"t" : a.ctype, "n" : a.name})
c_epilogue.append( "%(t)s_to_Mat( %(n)s, %(n)s_mat );" % {"n" : a.name, "t" : a.ctype} ) c_epilogue.append( "%(t)s_to_Mat( %(n)s, %(n)s_mat );" % {"n" : a.name, "t" : a.ctype} )
else: else:
if "jn_args" in type_dict[a.ctype] and "Vec" not in a.ctype:
self.classes[fi.classname or self.Module].imports.add("org.opencv.core." + type_dict[a.ctype]['j_type'])
if 'String' in type_dict[a.ctype]['j_type']:
self.classes[fi.classname or self.Module].imports.add("java.lang.String")
fields = type_dict[a.ctype].get("jn_args", ((a.ctype, ""),)) fields = type_dict[a.ctype].get("jn_args", ((a.ctype, ""),))
if "I" in a.out or not a.out or a.ctype in self.classes: # input arg, pass by primitive fields if "I" in a.out or not a.out or a.ctype in self.classes: # input arg, pass by primitive fields
for f in fields: for f in fields:
@ -818,7 +855,6 @@ JNIEXPORT jdoubleArray JNICALL Java_org_opencv_core_Core_n_1getTextSize
{"n" : a.name, "t": ("("+type_dict[f[0]]["j_type"]+")", "")[f[0]=="double"], "f" : f[1], "i" : i} {"n" : a.name, "t": ("("+type_dict[f[0]]["j_type"]+")", "")[f[0]=="double"], "f" : f[1], "i" : i}
) )
i += 1 i += 1
#j_epilogue.append("%s.set(%s_out);" % (a.name, a.name))
j_epilogue.append("; ".join(set_vals) + "; ") j_epilogue.append("; ".join(set_vals) + "; ")
c_epilogue.append( \ c_epilogue.append( \
"jdouble tmp_%(n)s[%(cnt)i] = {%(args)s}; env->SetDoubleArrayRegion(%(n)s_out, 0, %(cnt)i, tmp_%(n)s);" % "jdouble tmp_%(n)s[%(cnt)i] = {%(args)s}; env->SetDoubleArrayRegion(%(n)s_out, 0, %(cnt)i, tmp_%(n)s);" %
@ -839,9 +875,10 @@ JNIEXPORT jdoubleArray JNICALL Java_org_opencv_core_Core_n_1getTextSize
# java part: # java part:
#java doc comment #java doc comment
## f_name = fi.name f_name = fi.name
## if fi.classname: if fi.classname:
## f_name = fi.classname + "::" + fi.name f_name = fi.classname + "::" + fi.name
java_doc = "//javadoc: " + f_name + "(%s)" % ", ".join([a.name for a in args])
j_code.write(" "*4 + java_doc + "\n") j_code.write(" "*4 + java_doc + "\n")
# public java wrapper method impl (calling native one above) # public java wrapper method impl (calling native one above)
@ -998,51 +1035,56 @@ JNIEXPORT $rtype JNICALL Java_org_opencv_${module}_${clazz}_$fname
def gen_funcs(self): def gen_class(self, name):
# generate the code for all the global functions # generate code for the class
fflist = self.funcs.items() if name == "Mat":
return
ci = self.classes[name]
# constants
if ci.private_consts:
self.java_code[name]['j_code'].write("""
private static final int
%s;\n\n""" % (",\n"+" "*12).join(["%s = %s" % (c.name, c.value) for c in ci.private_consts])
)
if ci.consts:
self.java_code[name]['j_code'].write("""
public static final int
%s;\n\n""" % (",\n"+" "*12).join(["%s = %s" % (c.name, c.value) for c in ci.consts])
)
# c-tors
fflist = ci.methods.items()
fflist.sort() fflist.sort()
for name, ffi in fflist: for n, ffi in fflist:
assert not ffi.funcs[0].classname, "Error: global func is a class member - "+name if ffi.isconstructor:
for fi in ffi.funcs: for fi in ffi.funcs:
self.gen_func(fi, len(ffi.funcs)>1) self.gen_func(fi, len(ffi.funcs)>1)
# other methods
for n, ffi in fflist:
def gen_classes(self): if not ffi.isconstructor:
# generate code for the classes (their methods and consts) for fi in ffi.funcs:
classlist = self.classes.items() self.gen_func(fi, len(ffi.funcs)>1)
classlist.sort() # props
for name, ci in classlist: for pi in ci.props:
if name == "Mat": # getter
continue getter_name = name + ".get_" + pi.name
# constants #print getter_name
self.gen_consts(ci.consts, self.java_code[name]["j_code"]) fi = FuncInfo( [getter_name, pi.ctype, [], []] ) # [ funcname, return_ctype, [modifiers], [args] ]
# c-tors self.gen_func2(fi, getter_name in ci.methods, pi.name)
fflist = ci.methods.items() if pi.rw:
fflist.sort() #setter
for n, ffi in fflist: setter_name = name + ".set_" + pi.name
if ffi.isconstructor: #print setter_name
for fi in ffi.funcs: fi = FuncInfo( [ setter_name, "void", [], [ [pi.ctype, pi.name, "", [], ""] ] ] )
self.gen_func(fi, len(ffi.funcs)>1) self.gen_func2(fi, getter_name in ci.methods, pi.name)
# other methods
for n, ffi in fflist: # manual ports
if not ffi.isconstructor: if name in ManualFuncs:
for fi in ffi.funcs: for func in ManualFuncs[name].keys():
self.gen_func(fi, len(ffi.funcs)>1) self.java_code[name]["j_code"].write ( ManualFuncs[name][func]["j_code"] )
# props self.java_code[name]["jn_code"].write( ManualFuncs[name][func]["jn_code"] )
for pi in ci.props: self.cpp_code.write( ManualFuncs[name][func]["cpp_code"] )
# getter
getter_name = name + ".get_" + pi.name if name != self.Module:
#print getter_name
fi = FuncInfo( [getter_name, pi.ctype, [], []] ) # [ funcname, return_ctype, [modifiers], [args] ]
self.gen_func2(fi, getter_name in ci.methods, "// %s %s" % (pi.ctype, pi.name), "//javadoc: %s::%s" % (name, pi.name), pi.name)
if pi.rw:
#setter
setter_name = name + ".set_" + pi.name
#print setter_name
fi = FuncInfo( [ setter_name, "void", [], [ [pi.ctype, pi.name, "", [], ""] ] ] )
self.gen_func2(fi, getter_name in ci.methods, "// %s %s" % (pi.ctype, pi.name), "//javadoc: %s::%s" % (name, pi.name), pi.name)
# finalize() # finalize()
self.java_code[name]["j_code"].write( self.java_code[name]["j_code"].write(
""" """
@ -1076,6 +1118,9 @@ JNIEXPORT void JNICALL Java_org_opencv_%(module)s_%(cls)s_n_1delete
""" % {"module" : module, "cls" : name} """ % {"module" : module, "cls" : name}
) )
self.java_code[name]["jn_code"].write( "\n// imports %i\n//" % len(ci.imports))
self.java_code[name]["jn_code"].write( "\n//".join(sorted(ci.imports)))
if __name__ == "__main__": if __name__ == "__main__":
if len(sys.argv) < 4: if len(sys.argv) < 4:

Loading…
Cancel
Save