gen_java.py 43.3 KB
Newer Older
A
Andrey Kamaev 已提交
1 2 3 4 5 6 7 8
import sys, re, os.path
from string import Template

try:
    from cStringIO import StringIO
except:
    from StringIO import StringIO

9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
class_ignore_list = (
    #core
    "FileNode",
    "FileStorage",
    #highgui
    "VideoWriter",
    "VideoCapture",
)

func_ignore_list = (
    #core
    "checkHardwareSupport",
    "setUseOptimized",
    "useOptimized",
    "vconcat",
    #highgui
    "namedWindow",
    "destroyWindow",
    "destroyAllWindows",
    "startWindowThread",
    "setWindowProperty",
    "getWindowProperty",
    "getTrackbarPos",
    "setTrackbarPos",
    "imshow",
    "waitKey",
)

37
const_ignore_list = (
L
Changed  
Leonid Beynenson 已提交
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
    "CV_CAP_OPENNI",
    "CV_CAP_PROP_OPENNI_",
    "WINDOW_AUTOSIZE",
    "CV_WND_PROP_",
    "CV_WINDOW_",
    "CV_EVENT_",
    "CV_GUI_",
    "CV_PUSH_BUTTON",
    "CV_CHECKBOX",
    "CV_RADIOBOX",

    #attention! the following constants are added to this list using code automatic generation -- should be checked
    "CV_CAP_ANY",
    "CV_CAP_MIL",
    "CV_CAP_VFW",
    "CV_CAP_V4L",
    "CV_CAP_V4L2",
    "CV_CAP_FIREWARE",
    "CV_CAP_FIREWIRE",
    "CV_CAP_IEEE1394",
    "CV_CAP_DC1394",
    "CV_CAP_CMU1394",
    "CV_CAP_STEREO",
    "CV_CAP_TYZX",
    "CV_TYZX_LEFT",
    "CV_TYZX_RIGHT",
    "CV_TYZX_COLOR",
    "CV_TYZX_Z",
    "CV_CAP_QT",
    "CV_CAP_UNICAP",
    "CV_CAP_DSHOW",
    "CV_CAP_PVAPI",
    "CV_CAP_PROP_DC1394_OFF",
    "CV_CAP_PROP_DC1394_MODE_MANUAL",
    "CV_CAP_PROP_DC1394_MODE_AUTO",
    "CV_CAP_PROP_DC1394_MODE_ONE_PUSH_AUTO",
    "CV_CAP_PROP_POS_MSEC",
    "CV_CAP_PROP_POS_FRAMES",
    "CV_CAP_PROP_POS_AVI_RATIO",
    "CV_CAP_PROP_FPS",
    "CV_CAP_PROP_FOURCC",
    "CV_CAP_PROP_FRAME_COUNT",
    "CV_CAP_PROP_FORMAT",
    "CV_CAP_PROP_MODE",
    "CV_CAP_PROP_BRIGHTNESS",
    "CV_CAP_PROP_CONTRAST",
    "CV_CAP_PROP_SATURATION",
    "CV_CAP_PROP_HUE",
    "CV_CAP_PROP_GAIN",
    "CV_CAP_PROP_EXPOSURE",
    "CV_CAP_PROP_CONVERT_RGB",
    "CV_CAP_PROP_WHITE_BALANCE_BLUE_U",
    "CV_CAP_PROP_RECTIFICATION",
    "CV_CAP_PROP_MONOCROME",
    "CV_CAP_PROP_SHARPNESS",
    "CV_CAP_PROP_AUTO_EXPOSURE",
    "CV_CAP_PROP_GAMMA",
    "CV_CAP_PROP_TEMPERATURE",
    "CV_CAP_PROP_TRIGGER",
    "CV_CAP_PROP_TRIGGER_DELAY",
    "CV_CAP_PROP_WHITE_BALANCE_RED_V",
    "CV_CAP_PROP_MAX_DC1394",
    "CV_CAP_GSTREAMER_QUEUE_LENGTH",
    "CV_CAP_PROP_PVAPI_MULTICASTIP",
102 103 104 105 106 107 108 109
    "CV_CAP_PROP_SUPPORTED_PREVIEW_SIZES_STRING",
    "EVENT_.*",
    "CV_L?(BGRA?|RGBA?|GRAY|XYZ|YCrCb|Luv|Lab|HLS|YUV|HSV)\d*2L?(BGRA?|RGBA?|GRAY|XYZ|YCrCb|Luv|Lab|HLS|YUV|HSV).*",
    "CV_COLORCVT_MAX",
    "CV_.*Bayer.*",
    "CV_YUV420i2.+",
    "CV_TM_.+",
    "CV_FLOODFILL_.+",
110 111
)

112

113 114 115 116 117 118 119 120
# c_type    : { java/jni correspondence }
type_dict = {
# "simple"  : { j_type : "?", jn_type : "?", jni_type : "?", suffix : "?" },
    ""        : { "j_type" : "", "jn_type" : "long", "jni_type" : "jlong" }, # c-tor ret_type
    "void"    : { "j_type" : "void", "jn_type" : "void", "jni_type" : "void" },
    "env"     : { "j_type" : "", "jn_type" : "", "jni_type" : "JNIEnv*"},
    "cls"     : { "j_type" : "", "jn_type" : "", "jni_type" : "jclass"},
    "bool"    : { "j_type" : "boolean", "jn_type" : "boolean", "jni_type" : "jboolean", "suffix" : "Z" },
121 122
    "int"     : { "j_type" : "int", "jn_type" : "int", "jni_type" : "jint", "suffix" : "I" },
    "long"    : { "j_type" : "int", "jn_type" : "int", "jni_type" : "jint", "suffix" : "I" },
123 124 125 126
    "float"   : { "j_type" : "float", "jn_type" : "float", "jni_type" : "jfloat", "suffix" : "F" },
    "double"  : { "j_type" : "double", "jn_type" : "double", "jni_type" : "jdouble", "suffix" : "D" },
    "size_t"  : { "j_type" : "long", "jn_type" : "long", "jni_type" : "jlong", "suffix" : "J" },
    "__int64" : { "j_type" : "long", "jn_type" : "long", "jni_type" : "jlong", "suffix" : "J" },
127
    "int64"   : { "j_type" : "long", "jn_type" : "long", "jni_type" : "jlong", "suffix" : "J" },
128
    "double[]": { "j_type" : "double[]", "jn_type" : "double[]", "jni_type" : "jdoubleArray", "suffix" : "_3D" },
129 130 131 132 133 134 135 136
    "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_KeyPoint" : { "j_type" : "java.util.List<KeyPoint>", "jn_type" : "long", "jni_type" : "jlong", "jni_var" : "vector<KeyPoint> %(n)s", "suffix" : "J" },
    "vector_Rect" : { "j_type" : "java.util.List<Rect>", "jn_type" : "long", "jni_type" : "jlong", "jni_var" : "vector<Rect> %(n)s", "suffix" : "J" },
    "vector_uchar" : { "j_type" : "java.util.List<Byte>", "jn_type" : "long", "jni_type" : "jlong", "jni_var" : "vector<uchar> %(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_double" : { "j_type" : "java.util.List<Double>", "jn_type" : "long", "jni_type" : "jlong", "jni_var" : "vector<double> %(n)s", "suffix" : "J" },
137 138
# "complex" : { j_type : "?", jn_args : (("", ""),), jn_name : "", jni_var : "", jni_name : "", "suffix" : "?" },
    "Mat"     : { "j_type" : "Mat", "jn_type" : "long", "jn_args" : (("__int64", ".nativeObj"),),
139
                  "jni_var" : "Mat& %(n)s = *((Mat*)%(n)s_nativeObj)",
140
                  "jni_type" : "jlong", #"jni_name" : "*%(n)s",
141 142
                  "suffix" : "J" },
    "Point"   : { "j_type" : "Point", "jn_args" : (("double", ".x"), ("double", ".y")),
143
                  "jni_var" : "Point %(n)s((int)%(n)s_x, (int)%(n)s_y)", "jni_type" : "jdoubleArray",
144 145
                  "suffix" : "DD"},
    "Point2f" : { "j_type" : "Point", "jn_args" : (("double", ".x"), ("double", ".y")),
146
                  "jni_var" : "Point2f %(n)s((float)%(n)s_x, (float)%(n)s_y)", "jni_type" : "jdoubleArray",
147 148
                  "suffix" : "DD"},
    "Point2d" : { "j_type" : "Point", "jn_args" : (("double", ".x"), ("double", ".y")),
149
                  "jni_var" : "Point2d %(n)s(%(n)s_x, %(n)s_y)", "jni_type" : "jdoubleArray",
150 151
                  "suffix" : "DD"},
    "Point3i" : { "j_type" : "Point", "jn_args" : (("double", ".x"), ("double", ".y"), ("double", ".z")),
152
                  "jni_var" : "Point3i %(n)s((int)%(n)s_x, (int)%(n)s_y, (int)%(n)s_z)", "jni_type" : "jdoubleArray",
153 154
                  "suffix" : "DDD"},
    "Point3f" : { "j_type" : "Point", "jn_args" : (("double", ".x"), ("double", ".y"), ("double", ".z")),
155
                  "jni_var" : "Point3f %(n)s((float)%(n)s_x, (float)%(n)s_y, (float)%(n)s_z)", "jni_type" : "jdoubleArray",
156 157
                  "suffix" : "DDD"},
    "Point3d" : { "j_type" : "Point", "jn_args" : (("double", ".x"), ("double", ".y"), ("double", ".z")),
158
                  "jni_var" : "Point3d %(n)s(%(n)s_x, %(n)s_y, %(n)s_z)", "jni_type" : "jdoubleArray",
159 160
                  "suffix" : "DDD"},
    "Rect"    : { "j_type" : "Rect",  "jn_args" : (("int", ".x"), ("int", ".y"), ("int", ".width"), ("int", ".height")),
161
                  "jni_var" : "Rect %(n)s(%(n)s_x, %(n)s_y, %(n)s_width, %(n)s_height)", "jni_type" : "jdoubleArray",
162
                  "suffix" : "IIII"},
163
    "Size"    : { "j_type" : "Size",  "jn_args" : (("double", ".width"), ("double", ".height")),
164
                  "jni_var" : "Size %(n)s((int)%(n)s_width, (int)%(n)s_height)", "jni_type" : "jdoubleArray",
165 166
                  "suffix" : "DD"},
    "Size2f"  : { "j_type" : "Size",  "jn_args" : (("double", ".width"), ("double", ".height")),
167
                  "jni_var" : "Size2f %(n)s((float)%(n)s_width, (float)%(n)s_height)", "jni_type" : "jdoubleArray",
168 169
                  "suffix" : "DD"},
 "RotatedRect": { "j_type" : "RotatedRect",  "jn_args" : (("double", ".center.x"), ("double", ".center.y"), ("double", ".size.width"), ("double", ".size.height"), ("double", ".angle")),
170
                  "jni_var" : "RotatedRect %(n)s(cv::Point2f(%(n)s_center_x, %(n)s_center_y), cv::Size2f(%(n)s_size_width, %(n)s_size_height), %(n)s_angle)",
171
                  "jni_type" : "jdoubleArray", "suffix" : "DDDDD"},
172 173
    "Scalar"  : { "j_type" : "Scalar",  "jn_args" : (("double", ".val[0]"), ("double", ".val[1]"), ("double", ".val[2]"), ("double", ".val[3]")),
                  "jni_var" : "Scalar %(n)s(%(n)s_val0, %(n)s_val1, %(n)s_val2, %(n)s_val3)", "jni_type" : "jdoubleArray",
174
                  "suffix" : "DDDD"},
175
    "Range"   : { "j_type" : "Range",  "jn_args" : (("int", ".start"), ("int", ".end")),
176
                  "jni_var" : "Range %(n)s(%(n)s_start, %(n)s_end)", "jni_type" : "jdoubleArray",
177
                  "suffix" : "II"},
L
Leonid Beynenson 已提交
178
    "CvSlice" : { "j_type" : "Range",  "jn_args" : (("int", ".start"), ("int", ".end")),
179
                  "jni_var" : "Range %(n)s(%(n)s_start, %(n)s_end)", "jni_type" : "jdoubleArray",
180
                  "suffix" : "II"},
181 182
    "string"  : { "j_type" : "java.lang.String",  "jn_type" : "java.lang.String",
                  "jni_type" : "jstring", "jni_name" : "n_%(n)s",
183
                  "jni_var" : 'const char* utf_%(n)s = env->GetStringUTFChars(%(n)s, 0); std::string n_%(n)s( utf_%(n)s ? utf_%(n)s : "" ); env->ReleaseStringUTFChars(%(n)s, utf_%(n)s)',
184
                  "suffix" : "Ljava_lang_String_2"},
185 186 187 188
    "String"  : { "j_type" : "java.lang.String",  "jn_type" : "java.lang.String",
                  "jni_type" : "jstring", "jni_name" : "n_%(n)s",
                  "jni_var" : 'const char* utf_%(n)s = env->GetStringUTFChars(%(n)s, 0); String n_%(n)s( utf_%(n)s ? utf_%(n)s : "" ); env->ReleaseStringUTFChars(%(n)s, utf_%(n)s)',
                  "suffix" : "Ljava_lang_String_2"},
189 190 191 192
    "c_string": { "j_type" : "java.lang.String",  "jn_type" : "java.lang.String",
                  "jni_type" : "jstring", "jni_name" : "n_%(n)s.c_str()",
                  "jni_var" : 'const char* utf_%(n)s = env->GetStringUTFChars(%(n)s, 0); std::string n_%(n)s( utf_%(n)s ? utf_%(n)s : "" ); env->ReleaseStringUTFChars(%(n)s, utf_%(n)s)',
                  "suffix" : "Ljava_lang_String_2"},
L
Leonid Beynenson 已提交
193 194 195
"TermCriteria": { "j_type" : "TermCriteria",  "jn_args" : (("int", ".type"), ("int", ".maxCount"), ("double", ".epsilon")),
                  "jni_var" : "TermCriteria %(n)s(%(n)s_type, %(n)s_maxCount, %(n)s_epsilon)",
                  "suffix" : "IID"},
196 197 198 199
    "Vec3d"   : { "j_type" : "double[]",  "jn_args" : (("double", ".val[0]"), ("double", ".val[1]"), ("double", ".val[2]")),
                  "jn_type" : "double[]",
                  "jni_var" : "Vec3d %(n)s(%(n)s_val0, %(n)s_val1, %(n)s_val2)", "jni_type" : "jdoubleArray",
                  "suffix" : "DDD"},
A
Andrey Kamaev 已提交
200 201 202

}

A
Andrey Kamaev 已提交
203
setManualFunctions=set(['minMaxLoc', 'getTextSize'])
204

A
Andrey Kamaev 已提交
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
class ConstInfo(object):
    def __init__(self, cname, name, val):
##        self.name = re.sub(r"^cv\.", "", name).replace(".", "_")
        self.cname = cname
        self.name =  re.sub(r"^Cv", "", name)
        #self.name = re.sub(r"([a-z])([A-Z])", r"\1_\2", name)
        #self.name = self.name.upper()
        self.value = val


class ClassInfo(object):
    def __init__(self, decl): # [ 'class/struct cname', [bases], [modlist] ]
        name = decl[0]
        name = name[name.find(" ")+1:].strip()
        self.cname = self.name = self.jname = re.sub(r"^cv\.", "", name)
        self.cname =self.cname.replace(".", "::")
221
        #self.jname =  re.sub(r"^Cv", "", self.jname)
A
Andrey Kamaev 已提交
222 223 224 225 226 227 228 229 230
        self.methods = {}
        self.consts = [] # using a list to save the occurence order
        for m in decl[2]:
            if m.startswith("="):
                self.jname = m[1:]


class ArgInfo(object):
    def __init__(self, arg_tuple): # [ ctype, name, def val, [mod], argno ]
231 232 233 234 235 236
        self.pointer = False
        ctype = arg_tuple[0]
        if ctype.endswith("*"):
            ctype = ctype[:-1]
            self.pointer = True
        self.ctype = ctype
A
Andrey Kamaev 已提交
237 238
        self.name = arg_tuple[1]
        self.defval = arg_tuple[2]
239 240 241 242 243
        self.out = ""
        if "/O" in arg_tuple[3]:
            self.out = "O"
        if "/IO" in arg_tuple[3]:
            self.out = "IO"
A
Andrey Kamaev 已提交
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268


class FuncInfo(object):
    def __init__(self, decl): # [ funcname, return_ctype, [modifiers], [args] ]
        name = re.sub(r"^cv\.", "", decl[0])
        self.cname = name.replace(".", "::")
        classname = ""
        dpos = name.rfind(".")
        if dpos >= 0:
            classname = name[:dpos]
            name = name[dpos+1:]
        self.classname = classname
        self.jname = self.name = name
        if "[" in name:
            self.jname = "getelem"
        for m in decl[2]:
            if m.startswith("="):
                self.jname = m[1:]
        self.jn_name = "n_" + self.jname
        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.ctype = decl[1] or ""
        self.args = []
269 270 271
        #self.jni_suffix = "__"
        #if self.classname and self.ctype and not self.static: # non-static class methods except c-tors
        #    self.jni_suffix += "J" # artifical 'self'
A
Andrey Kamaev 已提交
272 273 274
        for a in decl[3]:
            ai = ArgInfo(a)
            self.args.append(ai)
275
        #    self.jni_suffix += ctype2j.get(ai.ctype, ["","","",""])[3]
A
Andrey Kamaev 已提交
276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301



class FuncFamilyInfo(object):
    def __init__(self, decl): # [ funcname, return_ctype, [modifiers], [args] ]
        self.funcs = []
        self.funcs.append( FuncInfo(decl) )
        self.jname = self.funcs[0].jname
        self.isconstructor = self.funcs[0].name == self.funcs[0].classname



    def add_func(self, fi):
        self.funcs.append( fi )


class JavaWrapperGenerator(object):
    def __init__(self):
        self.clear()

    def clear(self):
        self.classes = { "Mat" : ClassInfo([ 'class Mat', [], [] ]) }
        self.funcs = {}
        self.consts = [] # using a list to save the occurence order
        self.module = ""
        self.java_code = StringIO()
302
        self.jn_code = StringIO()
A
Andrey Kamaev 已提交
303 304
        self.cpp_code = StringIO()
        self.ported_func_counter = 0
305 306 307
        self.ported_func_list = []
        self.skipped_func_list = []
        self.total_func_counter = 0
A
Andrey Kamaev 已提交
308 309 310

    def add_class(self, decl):
        classinfo = ClassInfo(decl)
311 312
        if classinfo.name in class_ignore_list:
            return
A
Andrey Kamaev 已提交
313 314 315 316 317
        if classinfo.name in self.classes:
            print "Generator error: class %s (%s) is duplicated" % \
                    (classinfo.name, classinfo.cname)
            sys.exit(-1)
        self.classes[classinfo.name] = classinfo
318
        if classinfo.name in type_dict:
A
Andrey Kamaev 已提交
319 320
            print "Duplicated class: " + classinfo.name
            sys.exit(-1)
321
        type_dict[classinfo.name] = \
322 323 324
            { "j_type" : classinfo.name,
              "jn_type" : "long", "jn_args" : (("__int64", ".nativeObj"),),
              "jni_name" : "(*("+classinfo.name+"*)%(n)s_nativeObj)", "jni_type" : "jlong",
325
              "suffix" : "J" }
A
Andrey Kamaev 已提交
326 327 328 329 330 331 332


    def add_const(self, decl): # [ "const cname", val, [], [] ]
        consts = self.consts
        name = decl[0].replace("const ", "").strip()
        name = re.sub(r"^cv\.", "", name)
        cname = name.replace(".", "::")
333 334 335
        for c in const_ignore_list:
            if re.match(c, name):
                return
A
Andrey Kamaev 已提交
336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357
        # check if it's a class member
        dpos = name.rfind(".")
        if dpos >= 0:
            classname = name[:dpos]
            name = name[dpos+1:]
            if classname in self.classes:
                consts = self.classes[classname].consts
            else:
                # this class isn't wrapped
                # skipping this const
                return
        constinfo = ConstInfo(cname, name, decl[1])
        # checking duplication
        for c in consts:
            if c.name == constinfo.name:
                print "Generator error: constant %s (%s) is duplicated" \
                        % (constinfo.name, constinfo.cname)
                sys.exit(-1)
        consts.append(constinfo)

    def add_func(self, decl):
        ffi = FuncFamilyInfo(decl)
358
	if ffi.jname in setManualFunctions :
359
		print "Found function, which is ported manually: " + ffi.jname
360
		return None
A
Andrey Kamaev 已提交
361 362
        func_map = self.funcs
        classname = ffi.funcs[0].classname
363 364
        if classname in class_ignore_list or ffi.jname in func_ignore_list:
            return
A
Andrey Kamaev 已提交
365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401
        if classname:
            if classname in self.classes:
                func_map = self.classes[classname].methods
            else:
                print "Generator error: the class %s for method %s is missing" % \
                        (classname, ffi.jname)
                sys.exit(-1)
        if ffi.jname in func_map:
            func_map[ffi.jname].add_func(ffi.funcs[0])
        else:
            func_map[ffi.jname] = ffi

    def save(self, path, name, buf):
        f = open(path + "/" + name, "wt")
        f.write(buf.getvalue())
        f.close()

    def gen(self, srcfiles, module, output_path):
        self.clear()
        self.module = module
        parser = hdr_parser.CppHeaderParser()

        # step 1: scan the headers and build more descriptive maps of classes, consts, functions
        for hdr in srcfiles:
            decls = parser.parse(hdr)
            for decl in decls:
                name = decl[0]
                if name.startswith("struct") or name.startswith("class"):
                    self.add_class(decl)
                    pass
                elif name.startswith("const"):
                    self.add_const(decl)
                else: # function
                    self.add_func(decl)
                    pass

        # java module header
402
        self.java_code.write("package org.opencv;\n\npublic class %s {\n" % module)
A
Andrey Kamaev 已提交
403

404 405 406 407
        if module == "core":
            self.java_code.write(\
"""
    private static final int
A
Andrey Kamaev 已提交
408 409 410 411 412 413 414
            CV_8U  = 0,
            CV_8S  = 1,
            CV_16U = 2,
            CV_16S = 3,
            CV_32S = 4,
            CV_32F = 5,
            CV_64F = 6,
415 416
            CV_USRTYPE1 = 7;

417 418
    //Manual ported functions

419
    // C++: minMaxLoc(Mat src, double* minVal, double* maxVal=0, Point* minLoc=0, Point* maxLoc=0, InputArray mask=noArray())
420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438
    //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;
        }
L
Leonid Beynenson 已提交
439
        double resarr[] = n_minMaxLocManual(src.nativeObj, maskNativeObj);
440 441 442 443 444 445 446 447 448 449 450
        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);
    }
L
Leonid Beynenson 已提交
451
    private static native double[] n_minMaxLocManual(long src_nativeObj, long mask_nativeObj);
452

A
Andrey Kamaev 已提交
453 454 455 456 457 458 459
    //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);
460

461 462 463 464 465 466
""" )

        if module == "imgproc":
            self.java_code.write(\
"""
    public static final int
A
Andrey Kamaev 已提交
467 468 469 470 471 472
            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;
473
""" )
474

A
Andrey Pavlenko 已提交
475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505
        if module == "calib3d":
            self.java_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;
""" )

506 507 508 509 510 511 512 513
        # java native stuff
        self.jn_code.write("""
    //
    // native stuff
    //
    static { System.loadLibrary("opencv_java");	}
""")

A
Andrey Kamaev 已提交
514 515
        # cpp module header
        self.cpp_code.write(\
516 517 518
"""//
// This file is auto-generated, please don't edit!
//
A
Andrey Kamaev 已提交
519 520

#include <jni.h>
521 522

#ifdef DEBUG
523
#include <android/log.h>
524 525
#define MODULE_LOG_TAG "OpenCV.%s"
#define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, MODULE_LOG_TAG, __VA_ARGS__))
526 527 528
#else //DEBUG
#define LOGD(...)
#endif //DEBUG
A
Andrey Kamaev 已提交
529

530
#include "utils.h"
531
""" % module)
A
Andrey Kamaev 已提交
532 533
        self.cpp_code.write( "\n".join(['#include "opencv2/%s/%s"' % (module, os.path.basename(f)) \
                            for f in srcfiles]) )
534
        self.cpp_code.write('\nusing namespace cv;\n')
535
        self.cpp_code.write('\n\nextern "C" {\n\n')
A
Andrey Kamaev 已提交
536 537 538 539 540 541 542 543

        # step 2: generate the code for global constants
        self.gen_consts()

        # step 3: generate the code for all the global functions
        self.gen_funcs()

        # step 4: generate code for the classes
544
        self.gen_classes()
A
Andrey Kamaev 已提交
545

546 547 548
        if module == "core":
            self.cpp_code.write(\
"""
L
Leonid Beynenson 已提交
549
JNIEXPORT jdoubleArray JNICALL Java_org_opencv_core_n_1minMaxLocManual
550 551 552 553 554 555 556 557 558
  (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 */
        }
559

560
        Mat& src = *((Mat*)src_nativeObj);
561

562 563 564 565 566 567 568 569
        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);
        }
570

571 572 573 574 575 576 577
        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;
578

579 580 581 582 583 584 585 586 587 588 589 590 591
        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/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");
A
Andrey Kamaev 已提交
592 593 594 595 596 597 598 599 600 601 602 603 604 605 606
        env->ThrowNew(je, "Unknown exception in JNI code {core::minMaxLoc()}");
        return NULL;
    }
}

JNIEXPORT jdoubleArray JNICALL Java_org_opencv_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 */
        }
607

A
Andrey Kamaev 已提交
608 609 610
        const char* utf_text = env->GetStringUTFChars(text, 0);
        std::string n_text( utf_text ? utf_text : "" );
        env->ReleaseStringUTFChars(text, utf_text);
611

A
Andrey Kamaev 已提交
612 613
        int _baseLine;
        int* pbaseLine = 0;
614

A
Andrey Kamaev 已提交
615 616
        if (baseLine != NULL)
            pbaseLine = &_baseLine;
617

A
Andrey Kamaev 已提交
618 619 620 621 622 623 624
        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);
625

A
Andrey Kamaev 已提交
626 627 628 629 630 631 632 633 634 635 636 637 638 639 640
        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/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()}");
641 642 643 644 645
        return NULL;
    }
}
""")

646
        # module tail
647
        self.java_code.write("\n\n" + self.jn_code.getvalue() + "\n")
A
Andrey Kamaev 已提交
648
        self.java_code.write("}\n")
649
        self.cpp_code.write('} // extern "C"\n')
A
Andrey Kamaev 已提交
650 651 652

        self.save(output_path, module+".java", self.java_code)
        self.save(output_path, module+".cpp",  self.cpp_code)
653 654 655 656 657 658 659 660 661 662 663
        # report
        report = StringIO()
        report.write("PORTED FUNCs LIST (%i of %i):\n\n" % \
            (self.ported_func_counter, self.total_func_counter) \
        )
        report.write("\n".join(self.ported_func_list))
        report.write("\n\nSKIPPED FUNCs LIST (%i of %i):\n\n" % \
            (self.total_func_counter - self.ported_func_counter, self.total_func_counter) \
        )
        report.write("".join(self.skipped_func_list))
        self.save(output_path, module+".txt", report)
A
Andrey Kamaev 已提交
664

665
        print "Done %i of %i funcs." % (self.ported_func_counter, self.total_func_counter)
A
Andrey Kamaev 已提交
666 667 668 669 670 671 672 673 674 675 676 677


    def gen_consts(self):
        # generate the code for global constants
        if self.consts:
            self.java_code.write("""
    public static final int
            """ + """,
            """.join(["%s = %s" % (c.name, c.value) for c in self.consts]) + \
            ";\n\n")


678
    def gen_func(self, fi, isoverload, jn_code):
679
        self.total_func_counter += 1
680
        # // C++: c_decl
A
Andrey Kamaev 已提交
681
        # e.g:
682
        # //  C++: void add(Mat src1, Mat src2, Mat dst, Mat mask = Mat(), int dtype = -1)
683 684 685 686 687 688 689 690 691 692 693 694 695 696
        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) )

697
        indent = " " * 4
A
Andrey Kamaev 已提交
698
        if fi.classname:
699
            indent += " " * 4
700
        # java comment
701
        self.java_code.write( "\n"+indent+"//\n"+indent+"// C++: "+c_decl+"\n"+indent+"//\n\n" )
A
Andrey Kamaev 已提交
702
        # check if we 'know' all the types
703
        if fi.ctype not in type_dict: # unsupported ret type
704
            msg = "// Return type '%s' is not supported, skipping the function\n\n" % fi.ctype
705
            self.skipped_func_list.append(c_decl + "\n" + msg)
706
            self.java_code.write( indent + msg )
707
            #self.cpp_code.write( msg )
A
Andrey Kamaev 已提交
708 709 710
            print "SKIP:", c_decl, "\n\tdue to RET type", fi.ctype
            return
        for a in fi.args:
711
            if a.ctype not in type_dict:
712
                msg = "// Unknown type '%s' (%s), skipping the function\n\n" % (a.ctype, a.out or "I")
713
                self.skipped_func_list.append(c_decl + "\n" + msg)
714
                self.java_code.write( indent + msg )
715
                #self.cpp_code.write( msg )
716
                print "SKIP:", c_decl, "\n\tdue to ARG type", a.ctype, "/" + (a.out or "I")
A
Andrey Kamaev 已提交
717 718 719
                return

        self.ported_func_counter += 1
720
        self.ported_func_list.append(c_decl)
721

722 723 724 725
        # jn & cpp comment
        jn_code.write( "\n%s// C++: %s\n" % (indent, c_decl) )
        self.cpp_code.write( "\n//\n// %s\n//\n" % c_decl )

A
Andrey Kamaev 已提交
726
        # java args
727
        args = fi.args[:] # copy
A
Andrey Kamaev 已提交
728 729 730 731 732
        if args and args[-1].defval:
            isoverload = True

        while True:

733
             # java native method args
A
Andrey Kamaev 已提交
734 735 736
            jn_args = []
            # jni (cpp) function args
            jni_args = [ArgInfo([ "env", "env", "", [], "" ]), ArgInfo([ "cls", "cls", "", [], "" ])]
737
            suffix = "__"
738 739 740 741 742
            j_prologue = []
            j_epilogue = []
            c_prologue = []
            c_epilogue = []
            if type_dict[fi.ctype]["jni_type"] == "jdoubleArray":
743 744 745 746 747 748
                fields = type_dict[fi.ctype]["jn_args"]
                c_epilogue.append( \
                    ("jdoubleArray _da_retval_ = env->NewDoubleArray(%(cnt)i);  " +
                     "jdouble _tmp_retval_[%(cnt)i] = {%(args)s}; " +
                     "env->SetDoubleArrayRegion(_da_retval_, 0, %(cnt)i, _tmp_retval_);") %
                    { "cnt" : len(fields), "args" : ", ".join(["_retval_" + f[1] for f in fields]) } )
749 750 751 752 753
            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", "", [], "" ]) )
                jni_args.append( ArgInfo([ "__int64", "self", "", [], "" ]) )
                suffix += "J"
A
Andrey Kamaev 已提交
754
            for a in args:
755
                suffix += type_dict[a.ctype].get("suffix") or ""
756 757 758 759 760

                if "vector" in a.ctype: # pass as Mat
                    jn_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} + ";" )
761
                    c_prologue.append( "Mat& %(n)s_mat = *((Mat*)%(n)s_mat_nativeObj)" % {"n" : a.name} + ";" )
762
                    if "I" in a.out or not a.out:
763 764
                        j_prologue.append( "Mat %(n)s_mat = utils.%(t)s_to_Mat(%(n)s);" % {"n" : a.name, "t" : a.ctype} )
                        c_prologue.append( "Mat_to_%(t)s( %(n)s_mat, %(n)s );" % {"n" : a.name, "t" : a.ctype} )
765 766 767
                    else:
                        j_prologue.append( "Mat %s_mat = new Mat();" % a.name )
                    if "O" in a.out:
768
                        j_epilogue.append("utils.Mat_to_%(t)s(%(n)s_mat, %(n)s);" % {"t" : a.ctype, "n" : a.name})
769
                        c_epilogue.append( "%(t)s_to_Mat( %(n)s, %(n)s_mat );" % {"n" : a.name, "t" : a.ctype} )
A
Andrey Kamaev 已提交
770
                else:
771

772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792
                    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
                        for f in fields:
                            jn_args.append ( ArgInfo([ f[0], a.name + f[1], "", [], "" ]) )
                            jni_args.append( ArgInfo([ f[0], a.name + f[1].replace(".","_").replace("[","").replace("]",""), "", [], "" ]) )
                    if a.out and a.ctype not in self.classes: # out arg, pass as double[]
                        jn_args.append ( ArgInfo([ "double[]", "%s_out" % a.name, "", [], "" ]) )
                        jni_args.append ( ArgInfo([ "double[]", "%s_out" % a.name, "", [], "" ]) )
                        j_prologue.append( "double[] %s_out = new double[%i];" % (a.name, len(fields)) )
                        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}
                            )
                            i += 1
                        #j_epilogue.append("%s.set(%s_out);" % (a.name, a.name))
                        j_epilogue.append("; ".join(set_vals) + "; ")
                        c_epilogue.append( \
                            "jdouble tmp_%(n)s[%(cnt)i] = {%(args)s}; env->SetDoubleArrayRegion(%(n)s_out, 0, %(cnt)i, tmp_%(n)s);" %
                            { "n" : a.name, "cnt" : len(fields), "args" : ", ".join([a.name + f[1] for f in fields]) } )
793

A
Andrey Kamaev 已提交
794 795 796 797 798

            # java part:
            # private java NATIVE method decl
            # e.g.
            # private static native void n_add(long src1, long src2, long dst, long mask, int dtype);
799
            jn_code.write( Template(\
800
                "${indent}private static native $jn_type $jn_name($jn_args);\n").substitute(\
A
Andrey Kamaev 已提交
801
                indent = indent, \
802
                jn_type = type_dict[fi.ctype].get("jn_type", "double[]"), \
803
                jn_name = fi.jn_name, \
804
                jn_args = ", ".join(["%s %s" % (type_dict[a.ctype]["jn_type"], a.name.replace(".","_").replace("[","").replace("]","")) for a in jn_args])
A
Andrey Kamaev 已提交
805 806 807
            ) );

            # java part:
808 809 810 811 812 813 814 815 816

            #java doc comment
            f_name = fi.name
            if fi.classname:
                f_name = fi.classname + "::" + fi.name
            self.java_code.write(indent + "//javadoc: " + f_name + "(%s)\n" % \
                ", ".join([a.name for a in args])
            )

A
Andrey Kamaev 已提交
817 818 819 820
            # public java wrapper method impl (calling native one above)
            # e.g.
            # public static void add( Mat src1, Mat src2, Mat dst, Mat mask, int dtype )
            # { n_add( src1.nativeObj, src2.nativeObj, dst.nativeObj, mask.nativeObj, dtype );  }
821 822 823
            ret_val = type_dict[fi.ctype]["j_type"] + " retVal = "
            tail = ""
            ret = "return retVal;"
A
Andrey Kamaev 已提交
824
            if fi.ctype == "void":
825 826
                ret_val = ""
                ret = "return;"
A
Andrey Kamaev 已提交
827
            elif fi.ctype == "": # c-tor
828 829
                ret_val = "nativeObj = "
                ret = "return;"
A
Andrey Kamaev 已提交
830
            elif fi.ctype in self.classes: # wrapped class
831 832
                ret_val = type_dict[fi.ctype]["j_type"] + " retVal = new " + self.classes[fi.ctype].jname + "("
                tail = ")"
833
            elif "jn_type" not in type_dict[fi.ctype]:
834 835
                ret_val = type_dict[fi.ctype]["j_type"] + " retVal = new " + type_dict[fi.ctype]["j_type"] + "("
                tail = ")"
A
Andrey Kamaev 已提交
836 837 838 839 840 841

            static = "static"
            if fi.classname:
                static = fi.static

            self.java_code.write( Template(\
842 843 844 845 846 847 848
"""${indent}public $static $j_type $j_name($j_args)
$indent{
$indent    $prologue
$indent    $ret_val$jn_name($jn_args_call)$tail;
$indent    $epilogue
$indent    $ret
$indent}
A
Andrey Kamaev 已提交
849

850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865
"""
                ).substitute(\
                    indent = indent, \
                    ret = ret, \
                    ret_val = ret_val, \
                    tail = tail, \
                    prologue = "  ".join(j_prologue), \
                    epilogue = "  ".join(j_epilogue), \
                    static=static, \
                    j_type=type_dict[fi.ctype]["j_type"], \
                    j_name=fi.jname, \
                    j_args=", ".join(["%s %s" % (type_dict[a.ctype]["j_type"], a.name) for a in args]), \
                    jn_name=fi.jn_name, \
                    jn_args_call=", ".join( [a.name for a in jn_args] ),\
                )
            )
A
Andrey Kamaev 已提交
866 867

            # cpp part:
868 869
            # jni_func(..) { _retval_ = cv_func(..); return _retval_; }
            ret = "return _retval_;"
870
            default = "return 0;"
A
Andrey Kamaev 已提交
871
            if fi.ctype == "void":
872 873 874 875
                ret = "return;"
                default = "return;"
            elif not fi.ctype: # c-tor
                ret = "return (jlong) _retval_;"
876
            elif fi.ctype == "string":
877
                ret = "return env->NewStringUTF(_retval_.c_str());"
878
                default = 'return env->NewStringUTF("");'
879
            elif fi.ctype in self.classes: # wrapped class:
880
                ret = "return (jlong) new %s(_retval_);" % fi.ctype
881
            elif type_dict[fi.ctype]["jni_type"] == "jdoubleArray":
882
                ret = "return _da_retval_;"
A
Andrey Kamaev 已提交
883 884

            cvname = "cv::" + fi.name
885 886 887
            retval = fi.ctype + " _retval_ = "
            if fi.ctype == "void":
                retval = ""
A
Andrey Kamaev 已提交
888 889
            if fi.classname:
                if not fi.ctype: # c-tor
890 891
                    retval = fi.classname + "* _retval_ = "
                    cvname = "new " + fi.classname
A
Andrey Kamaev 已提交
892
                elif fi.static:
893
                    cvname = "%s::%s" % (fi.classname, fi.name)
A
Andrey Kamaev 已提交
894
                else:
895
                    cvname = "me->" + fi.name
896
                    c_prologue.append(\
897
                        "%(cls)s* me = (%(cls)s*) self; //TODO: check for NULL" \
898
                            % { "cls" : fi.classname} \
A
Andrey Kamaev 已提交
899 900 901
                    )
            cvargs = []
            for a in args:
902 903 904 905 906 907 908 909 910 911
                if a.pointer:
                    jni_name = "&%(n)s"
                else:
                    jni_name = "%(n)s"
                cvargs.append( type_dict[a.ctype].get("jni_name", jni_name) % {"n" : a.name})
                if "vector" not in a.ctype :
                    if ("I" in a.out or not a.out or a.ctype in self.classes) and "jni_var" in type_dict[a.ctype]: # complex type
                        c_prologue.append(type_dict[a.ctype]["jni_var"] % {"n" : a.name} + ";")
                    if a.out and "I" not in a.out and a.ctype not in self.classes:
                        c_prologue.append("%s %s;" % (a.ctype, a.name))
A
Andrey Kamaev 已提交
912

913
            rtype = type_dict[fi.ctype].get("jni_type", "jdoubleArray")
A
Andrey Kamaev 已提交
914 915 916 917 918 919
            self.cpp_code.write ( Template( \
"""

JNIEXPORT $rtype JNICALL Java_org_opencv_${module}_$fname
  ($args)
{
920
    try {
921
        LOGD("$module::$fname()");
922
        $prologue
923
        $retval$cvname( $cvargs );
924
        $epilogue
925
        $ret
926
    } catch(cv::Exception e) {
927
        LOGD("$module::$fname() catched cv::Exception: %s", e.what());
928 929 930
        jclass je = env->FindClass("org/opencv/CvException");
        if(!je) je = env->FindClass("java/lang/Exception");
        env->ThrowNew(je, e.what());
931
        $default
932
    } catch (...) {
933
        LOGD("$module::$fname() catched unknown exception (...)");
934 935
        jclass je = env->FindClass("java/lang/Exception");
        env->ThrowNew(je, "Unknown exception in JNI code {$module::$fname()}");
936
        $default
937
    }
A
Andrey Kamaev 已提交
938 939
}

940

A
Andrey Kamaev 已提交
941 942 943 944
""" ).substitute( \
        rtype = rtype, \
        module = self.module, \
        fname = fi.jni_name + ["",suffix][isoverload], \
945
        args = ", ".join(["%s %s" % (type_dict[a.ctype].get("jni_type"), a.name) for a in jni_args]), \
946 947
        prologue = "\n        ".join(c_prologue), \
        epilogue = "  ".join(c_epilogue), \
A
Andrey Kamaev 已提交
948 949 950
        ret = ret, \
        cvname = cvname, \
        cvargs = ", ".join([a for a in cvargs]), \
951 952
        default = default, \
        retval = retval, \
A
Andrey Kamaev 已提交
953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970
    ) )

            # processing args with default values
            if args and args[-1].defval:
                a = args.pop()
            else:
                break



    def gen_funcs(self):
        # generate the code for all the global functions
        indent = "\t"
        fflist = self.funcs.items()
        fflist.sort()
        for name, ffi in fflist:
            assert not ffi.funcs[0].classname, "Error: global func is a class member - "+name
            for fi in ffi.funcs:
971
                self.gen_func(fi, len(ffi.funcs)>1, self.jn_code)
A
Andrey Kamaev 已提交
972 973 974 975


    def gen_classes(self):
        # generate code for the classes (their methods and consts)
976 977
        indent = " " * 4
        indent_m = indent + " " * 4
A
Andrey Kamaev 已提交
978 979 980
        classlist = self.classes.items()
        classlist.sort()
        for name, ci in classlist:
981
            if name == "Mat":
982 983
                continue
            self.java_code.write( "\n\n" + indent + "// C++: class %s" % (ci.cname) + "\n" )
984
            self.java_code.write( indent + "//javadoc: " + name + "\n" ) #java doc comment
A
Andrey Kamaev 已提交
985 986 987 988 989 990 991
            self.java_code.write( indent + "public static class %s {\n\n" % (ci.jname) )
            # self
            self.java_code.write( indent_m + "protected final long nativeObj;\n" )
            self.java_code.write( indent_m + "protected %s(long addr) { nativeObj = addr; }\n\n" \
                % name );
            # constants
            if ci.consts:
992
                prefix = "\n" + indent_m + "\t"
A
Andrey Kamaev 已提交
993 994 995
                s = indent_m + "public static final int" + prefix +\
                    ("," + prefix).join(["%s = %s" % (c.name, c.value) for c in ci.consts]) + ";\n\n"
                self.java_code.write( s )
996 997
            # methods
            jn_code = StringIO()
A
Andrey Kamaev 已提交
998 999 1000 1001 1002 1003
            # c-tors
            fflist = ci.methods.items()
            fflist.sort()
            for n, ffi in fflist:
                if ffi.isconstructor:
                    for fi in ffi.funcs:
1004
                        self.gen_func(fi, len(ffi.funcs)>1, jn_code)
A
Andrey Kamaev 已提交
1005 1006 1007 1008
            self.java_code.write( "\n" )
            for n, ffi in fflist:
                if not ffi.isconstructor:
                    for fi in ffi.funcs:
1009
                        self.gen_func(fi, len(ffi.funcs)>1, jn_code)
A
Andrey Kamaev 已提交
1010

1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023
            # finalize()
            self.java_code.write(
"""
        @Override
        protected void finalize() throws Throwable {
            n_delete(nativeObj);
            super.finalize();
        }

"""
            )

            self.java_code.write(indent_m + "// native stuff\n\n")
1024
            self.java_code.write(indent_m + 'static { System.loadLibrary("opencv_java"); }\n')
1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049
            self.java_code.write( jn_code.getvalue() )
            self.java_code.write(
"""
        // native support for java finalize()
        private static native void n_delete(long nativeObj);
"""
            )
            self.java_code.write("\n" + indent + "}\n\n")

            # native support for java finalize()
            self.cpp_code.write( \
"""
//
//  native support for java finalize()
//  static void %(cls)s::n_delete( __int64 self )
//

JNIEXPORT void JNICALL Java_org_opencv_%(module)s_00024%(cls)s_n_1delete
  (JNIEnv* env, jclass cls, jlong self)
{
    delete (%(cls)s*) self;
}

""" % {"module" : module, "cls" : name}
            )
A
Andrey Kamaev 已提交
1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071


if __name__ == "__main__":
    if len(sys.argv) < 4:
        print "Usage:\n", \
            os.path.basename(sys.argv[0]), \
            "<full path to hdr_parser.py> <module name> <C++ header> [<C++ header>...]"
        print "Current args are: ", ", ".join(["'"+a+"'" for a in sys.argv])
        exit(0)

    dstdir = "."
    hdr_parser_path = os.path.abspath(sys.argv[1])
    if hdr_parser_path.endswith(".py"):
        hdr_parser_path = os.path.dirname(hdr_parser_path)
    sys.path.append(hdr_parser_path)
    import hdr_parser
    module = sys.argv[2]
    srcfiles = sys.argv[3:]
    print "Generating module '" + module + "' from headers:\n\t" + "\n\t".join(srcfiles)
    generator = JavaWrapperGenerator()
    generator.gen(srcfiles, module, dstdir)