gen_java.py 40.1 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
const_ignore_list = (
L
Changed  
Leonid Beynenson 已提交
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 37 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
    "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",
74 75
)

76 77 78 79 80 81 82 83 84 85 86 87 88
func_ignore_list = (
    "namedWindow",
    "destroyWindow",
    "destroyAllWindows",
    "startWindowThread",
    "setWindowProperty",
    "getWindowProperty",
    "getTrackbarPos",
    "setTrackbarPos",
    "imshow",
    "waitKey",
)

89 90
class_ignore_list = (
    "VideoWriter",
91
    "VideoCapture",
92
)
93

94 95 96 97 98 99 100 101
# 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" },
102 103
    "int"     : { "j_type" : "int", "jn_type" : "int", "jni_type" : "jint", "suffix" : "I" },
    "long"    : { "j_type" : "int", "jn_type" : "int", "jni_type" : "jint", "suffix" : "I" },
104 105 106 107
    "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" },
108
    "double[]": { "j_type" : "double[]", "jn_type" : "double[]", "jni_type" : "jdoubleArray", "suffix" : "_3D" },
109 110 111 112 113 114 115 116
    "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" },
117 118
# "complex" : { j_type : "?", jn_args : (("", ""),), jn_name : "", jni_var : "", jni_name : "", "suffix" : "?" },
    "Mat"     : { "j_type" : "Mat", "jn_type" : "long", "jn_args" : (("__int64", ".nativeObj"),),
119
                  "jni_var" : "Mat& %(n)s = *((Mat*)%(n)s_nativeObj)",
120
                  "jni_type" : "jlong", #"jni_name" : "*%(n)s",
121 122
                  "suffix" : "J" },
    "Point"   : { "j_type" : "Point", "jn_args" : (("double", ".x"), ("double", ".y")),
123
                  "jni_var" : "Point %(n)s((int)%(n)s_x, (int)%(n)s_y)", "jni_type" : "jdoubleArray",
124 125
                  "suffix" : "DD"},
    "Point2f" : { "j_type" : "Point", "jn_args" : (("double", ".x"), ("double", ".y")),
126
                  "jni_var" : "Point2f %(n)s((float)%(n)s_x, (float)%(n)s_y)", "jni_type" : "jdoubleArray",
127 128
                  "suffix" : "DD"},
    "Point2d" : { "j_type" : "Point", "jn_args" : (("double", ".x"), ("double", ".y")),
129
                  "jni_var" : "Point2d %(n)s(%(n)s_x, %(n)s_y)", "jni_type" : "jdoubleArray",
130 131
                  "suffix" : "DD"},
    "Point3i" : { "j_type" : "Point", "jn_args" : (("double", ".x"), ("double", ".y"), ("double", ".z")),
132
                  "jni_var" : "Point3i %(n)s((int)%(n)s_x, (int)%(n)s_y, (int)%(n)s_z)", "jni_type" : "jdoubleArray",
133 134
                  "suffix" : "DDD"},
    "Point3f" : { "j_type" : "Point", "jn_args" : (("double", ".x"), ("double", ".y"), ("double", ".z")),
135
                  "jni_var" : "Point3f %(n)s((float)%(n)s_x, (float)%(n)s_y, (float)%(n)s_z)", "jni_type" : "jdoubleArray",
136 137
                  "suffix" : "DDD"},
    "Point3d" : { "j_type" : "Point", "jn_args" : (("double", ".x"), ("double", ".y"), ("double", ".z")),
138
                  "jni_var" : "Point3d %(n)s(%(n)s_x, %(n)s_y, %(n)s_z)", "jni_type" : "jdoubleArray",
139 140
                  "suffix" : "DDD"},
    "Rect"    : { "j_type" : "Rect",  "jn_args" : (("int", ".x"), ("int", ".y"), ("int", ".width"), ("int", ".height")),
141
                  "jni_var" : "Rect %(n)s(%(n)s_x, %(n)s_y, %(n)s_width, %(n)s_height)", "jni_type" : "jdoubleArray",
142
                  "suffix" : "IIII"},
143
    "Size"    : { "j_type" : "Size",  "jn_args" : (("double", ".width"), ("double", ".height")),
144
                  "jni_var" : "Size %(n)s((int)%(n)s_width, (int)%(n)s_height)", "jni_type" : "jdoubleArray",
145 146
                  "suffix" : "DD"},
    "Size2f"  : { "j_type" : "Size",  "jn_args" : (("double", ".width"), ("double", ".height")),
147
                  "jni_var" : "Size2f %(n)s((float)%(n)s_width, (float)%(n)s_height)", "jni_type" : "jdoubleArray",
148 149
                  "suffix" : "DD"},
 "RotatedRect": { "j_type" : "RotatedRect",  "jn_args" : (("double", ".center.x"), ("double", ".center.y"), ("double", ".size.width"), ("double", ".size.height"), ("double", ".angle")),
150
                  "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)",
151
                  "jni_type" : "jdoubleArray", "suffix" : "DDDDD"},
152 153
    "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",
154
                  "suffix" : "DDDD"},
155
    "Range"   : { "j_type" : "Range",  "jn_args" : (("int", ".start"), ("int", ".end")),
156
                  "jni_var" : "Range %(n)s(%(n)s_start, %(n)s_end)", "jni_type" : "jdoubleArray",
157
                  "suffix" : "II"},
L
Leonid Beynenson 已提交
158
    "CvSlice" : { "j_type" : "Range",  "jn_args" : (("int", ".start"), ("int", ".end")),
159
                  "jni_var" : "Range %(n)s(%(n)s_start, %(n)s_end)", "jni_type" : "jdoubleArray",
160
                  "suffix" : "II"},
161 162
    "string"  : { "j_type" : "java.lang.String",  "jn_type" : "java.lang.String",
                  "jni_type" : "jstring", "jni_name" : "n_%(n)s",
163
                  "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)',
164
                  "suffix" : "Ljava_lang_String_2"},
165 166 167 168
    "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"},
169 170 171 172
    "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 已提交
173 174 175
"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"},
A
Andrey Kamaev 已提交
176 177 178

}

179 180
setManualFunctions=set(['minMaxLoc'])

A
Andrey Kamaev 已提交
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
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(".", "::")
197
        #self.jname =  re.sub(r"^Cv", "", self.jname)
A
Andrey Kamaev 已提交
198 199 200 201 202 203 204 205 206 207 208 209
        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 ]
        self.ctype = arg_tuple[0]
        self.name = arg_tuple[1]
        self.defval = arg_tuple[2]
210 211 212 213 214
        self.out = ""
        if "/O" in arg_tuple[3]:
            self.out = "O"
        if "/IO" in arg_tuple[3]:
            self.out = "IO"
A
Andrey Kamaev 已提交
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239


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 = []
240 241 242
        #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 已提交
243 244 245
        for a in decl[3]:
            ai = ArgInfo(a)
            self.args.append(ai)
246
        #    self.jni_suffix += ctype2j.get(ai.ctype, ["","","",""])[3]
A
Andrey Kamaev 已提交
247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272



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()
273
        self.jn_code = StringIO()
A
Andrey Kamaev 已提交
274 275
        self.cpp_code = StringIO()
        self.ported_func_counter = 0
276 277 278
        self.ported_func_list = []
        self.skipped_func_list = []
        self.total_func_counter = 0
A
Andrey Kamaev 已提交
279 280 281

    def add_class(self, decl):
        classinfo = ClassInfo(decl)
282 283
        if classinfo.name in class_ignore_list:
            return
A
Andrey Kamaev 已提交
284 285 286 287 288
        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
289
        if classinfo.name in type_dict:
A
Andrey Kamaev 已提交
290 291
            print "Duplicated class: " + classinfo.name
            sys.exit(-1)
292
        type_dict[classinfo.name] = \
293 294 295
            { "j_type" : classinfo.name,
              "jn_type" : "long", "jn_args" : (("__int64", ".nativeObj"),),
              "jni_name" : "(*("+classinfo.name+"*)%(n)s_nativeObj)", "jni_type" : "jlong",
296
              "suffix" : "J" }
A
Andrey Kamaev 已提交
297 298 299 300 301 302 303


    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(".", "::")
304 305 306
        for c in const_ignore_list:
            if re.match(c, name):
                return
A
Andrey Kamaev 已提交
307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328
        # 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)
329
	if ffi.jname in setManualFunctions :
330
		print "Found function, which is ported manually: " + ffi.jname
331
		return None
A
Andrey Kamaev 已提交
332 333
        func_map = self.funcs
        classname = ffi.funcs[0].classname
334 335
        if classname in class_ignore_list or ffi.jname in func_ignore_list:
            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 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372
        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
373
        self.java_code.write("package org.opencv;\n\npublic class %s {\n" % module)
A
Andrey Kamaev 已提交
374

375 376 377 378
        if module == "core":
            self.java_code.write(\
"""
    private static final int
A
Andrey Kamaev 已提交
379 380 381 382 383 384 385
            CV_8U  = 0,
            CV_8S  = 1,
            CV_16U = 2,
            CV_16S = 3,
            CV_32S = 4,
            CV_32F = 5,
            CV_64F = 6,
386 387
            CV_USRTYPE1 = 7;

388 389
    //Manual ported functions

390
    // C++: minMaxLoc(Mat src, double* minVal, double* maxVal=0, Point* minLoc=0, Point* maxLoc=0, InputArray mask=noArray())
391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409
    //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 已提交
410
        double resarr[] = n_minMaxLocManual(src.nativeObj, maskNativeObj);
411 412 413 414 415 416 417 418 419 420 421
        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 已提交
422
    private static native double[] n_minMaxLocManual(long src_nativeObj, long mask_nativeObj);
423 424


425 426 427 428 429 430
""" )

        if module == "imgproc":
            self.java_code.write(\
"""
    public static final int
A
Andrey Kamaev 已提交
431 432 433 434 435 436
            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;
437
""" )
438

A
Andrey Pavlenko 已提交
439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469
        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;
""" )

470 471 472 473 474 475 476 477
        # java native stuff
        self.jn_code.write("""
    //
    // native stuff
    //
    static { System.loadLibrary("opencv_java");	}
""")

A
Andrey Kamaev 已提交
478 479
        # cpp module header
        self.cpp_code.write(\
480 481 482
"""//
// This file is auto-generated, please don't edit!
//
A
Andrey Kamaev 已提交
483 484

#include <jni.h>
485 486

#ifdef DEBUG
487
#include <android/log.h>
488 489
#define MODULE_LOG_TAG "OpenCV.%s"
#define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, MODULE_LOG_TAG, __VA_ARGS__))
490
#endif // DEBUG
A
Andrey Kamaev 已提交
491

492
#include "utils.h"
493
""" % module)
A
Andrey Kamaev 已提交
494 495
        self.cpp_code.write( "\n".join(['#include "opencv2/%s/%s"' % (module, os.path.basename(f)) \
                            for f in srcfiles]) )
496
        self.cpp_code.write('\nusing namespace cv;\n')
497
        self.cpp_code.write('\n\nextern "C" {\n\n')
A
Andrey Kamaev 已提交
498 499 500 501 502 503 504 505

        # 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
506
        self.gen_classes()
A
Andrey Kamaev 已提交
507

508 509 510
        if module == "core":
            self.cpp_code.write(\
"""
L
Leonid Beynenson 已提交
511
JNIEXPORT jdoubleArray JNICALL Java_org_opencv_core_n_1minMaxLocManual
512 513 514 515 516 517 518 519 520 521 522 523
  (JNIEnv* env, jclass cls, jlong src_nativeObj, jlong mask_nativeObj)
{
    try {
#ifdef DEBUG
        LOGD("core::n_1minMaxLoc()");
#endif // DEBUG

        jdoubleArray result;
        result = env->NewDoubleArray(6);
        if (result == NULL) {
            return NULL; /* out of memory error thrown */
        }
524

525
        Mat& src = *((Mat*)src_nativeObj);
526

527 528 529 530 531 532 533 534
        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);
        }
535

536 537 538 539 540 541 542
        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;
543

544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566
        env->SetDoubleArrayRegion(result, 0, 6, fill);

	return result;

    } catch(cv::Exception e) {
#ifdef DEBUG
        LOGD("core::n_1minMaxLoc() catched cv::Exception: %s", e.what());
#endif // DEBUG
        jclass je = env->FindClass("org/opencv/CvException");
        if(!je) je = env->FindClass("java/lang/Exception");
        env->ThrowNew(je, e.what());
        return NULL;
    } catch (...) {
#ifdef DEBUG
        LOGD("core::n_1minMaxLoc() catched unknown exception (...)");
#endif // DEBUG
        jclass je = env->FindClass("java/lang/Exception");
        env->ThrowNew(je, "Unknown exception in JNI code {$module::$fname()}");
        return NULL;
    }
}
""")

567
        # module tail
568
        self.java_code.write("\n\n" + self.jn_code.getvalue() + "\n")
A
Andrey Kamaev 已提交
569
        self.java_code.write("}\n")
570
        self.cpp_code.write('} // extern "C"\n')
A
Andrey Kamaev 已提交
571 572 573

        self.save(output_path, module+".java", self.java_code)
        self.save(output_path, module+".cpp",  self.cpp_code)
574 575 576 577 578 579 580 581 582 583 584
        # 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 已提交
585

586
        print "Done %i of %i funcs." % (self.ported_func_counter, self.total_func_counter)
A
Andrey Kamaev 已提交
587 588 589 590 591 592 593 594 595 596 597 598


    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")


599
    def gen_func(self, fi, isoverload, jn_code):
600
        self.total_func_counter += 1
601
        # // C++: c_decl
A
Andrey Kamaev 已提交
602
        # e.g:
603
        # //  C++: void add(Mat src1, Mat src2, Mat dst, Mat mask = Mat(), int dtype = -1)
A
Andrey Kamaev 已提交
604 605 606
        c_decl = "%s %s %s(%s)" % \
            ( fi.static, fi.ctype, fi.cname, \
              ", ".join(a.ctype + " " + a.name + [""," = "+a.defval][bool(a.defval)] for a in fi.args) )
607
        indent = " " * 4
A
Andrey Kamaev 已提交
608
        if fi.classname:
609
            indent += " " * 4
610
        # java comment
611
        self.java_code.write( "\n"+indent+"//\n"+indent+"// C++: "+c_decl+"\n"+indent+"//\n\n" )
A
Andrey Kamaev 已提交
612
        # check if we 'know' all the types
613
        if fi.ctype not in type_dict: # unsupported ret type
614
            msg = "// Return type '%s' is not supported, skipping the function\n\n" % fi.ctype
615
            self.skipped_func_list.append(c_decl + "\n" + msg)
616
            self.java_code.write( indent + msg )
617
            #self.cpp_code.write( msg )
A
Andrey Kamaev 已提交
618 619 620
            print "SKIP:", c_decl, "\n\tdue to RET type", fi.ctype
            return
        for a in fi.args:
621
            if a.ctype not in type_dict:
622
                msg = "// Unknown type '%s' (%s), skipping the function\n\n" % (a.ctype, a.out or "I")
623
                self.skipped_func_list.append(c_decl + "\n" + msg)
624
                self.java_code.write( indent + msg )
625
                #self.cpp_code.write( msg )
626
                print "SKIP:", c_decl, "\n\tdue to ARG type", a.ctype, "/" + (a.out or "I")
A
Andrey Kamaev 已提交
627 628 629
                return

        self.ported_func_counter += 1
630
        self.ported_func_list.append(c_decl)
631

632 633 634 635
        # 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 已提交
636
        # java args
637
        args = fi.args[:] # copy
A
Andrey Kamaev 已提交
638 639 640 641 642
        if args and args[-1].defval:
            isoverload = True

        while True:

643
             # java native method args
A
Andrey Kamaev 已提交
644 645 646
            jn_args = []
            # jni (cpp) function args
            jni_args = [ArgInfo([ "env", "env", "", [], "" ]), ArgInfo([ "cls", "cls", "", [], "" ])]
647
            suffix = "__"
648 649 650 651 652
            j_prologue = []
            j_epilogue = []
            c_prologue = []
            c_epilogue = []
            if type_dict[fi.ctype]["jni_type"] == "jdoubleArray":
653 654 655 656 657 658 659 660
                fields = type_dict[fi.ctype].get("jn_args")
                if fields:
                    c_epilogue.append( \
                        "jdoubleArray _da_retval_ = env->NewDoubleArray(6); /* assuming '6' is enough*/  " +
                        "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]) } )
                else:
                    c_epilogue.append( "/* TODO: NYI !!! */" )
661 662 663 664 665
            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 已提交
666
            for a in args:
667
                suffix += type_dict[a.ctype].get("suffix") or ""
668 669 670 671 672

                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} + ";" )
673
                    c_prologue.append( "Mat& %(n)s_mat = *((Mat*)%(n)s_mat_nativeObj)" % {"n" : a.name} + ";" )
674
                    if "I" in a.out or not a.out:
675 676
                        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} )
677 678 679
                    else:
                        j_prologue.append( "Mat %s_mat = new Mat();" % a.name )
                    if "O" in a.out:
680
                        j_epilogue.append("utils.Mat_to_%(t)s(%(n)s_mat, %(n)s);" % {"t" : a.ctype, "n" : a.name})
681
                        c_epilogue.append( "%(t)s_to_Mat( %(n)s, %(n)s_mat );" % {"n" : a.name, "t" : a.ctype} )
A
Andrey Kamaev 已提交
682
                else:
683

684
                    fields = type_dict[a.ctype].get("jn_args")
685 686 687
                    if fields: # complex type
                        for f in fields:
                            jn_args.append ( ArgInfo([ f[0], a.name + f[1], "", [], "" ]) )
688
                            jni_args.append( ArgInfo([ f[0], a.name + f[1].replace(".","_").replace("[","").replace("]",""), "", [], "" ]) )
689 690 691 692 693 694 695 696 697 698 699
                    else:
                        jn_args.append(a)
                        jni_args.append(a)

                    if a.out and a.ctype not in self.classes:
                        # pass as double[]
                        jn_args.append ( ArgInfo([ "double[]", "%s_out" % a.name, "", [], "" ]) )
                        #jn_args.append ( ArgInfo([ "int", "%s_out.length" % a.name, "", [], "" ]) )
                        jni_args.append ( ArgInfo([ "double[]", "%s_out" % a.name, "", [], "" ]) )
                        #jni_args.append ( ArgInfo([ "int", "%s_out_length" % a.name, "", [], "" ]) )
                        j_prologue.append( "double[] %s_out = new double[%i];" % (a.name, len(type_dict[a.ctype].get("jn_args", [1]))) )
700 701 702 703 704 705
                        if fields:
                            j_epilogue.append("%s.set(%s_out);" % (a.name, a.name))
                            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]) } )
                        else:
706
                            j_epilogue.append("/* TODO: NYI: %s.set(%s_out); */" % (a.name, a.name))
707 708 709 710
                            c_epilogue.append( \
                                "jdouble tmp_%(n)s[1] = {%(n)s}; env->SetDoubleArrayRegion(%(n)s_out, 0, 1, tmp_%(n)s);" %
                                { "n" : a.name } )

A
Andrey Kamaev 已提交
711 712 713 714 715

            # 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);
716
            jn_code.write( Template(\
717
                "${indent}private static native $jn_type $jn_name($jn_args);\n").substitute(\
A
Andrey Kamaev 已提交
718
                indent = indent, \
719
                jn_type = type_dict[fi.ctype].get("jn_type", "double[]"), \
720
                jn_name = fi.jn_name, \
721
                jn_args = ", ".join(["%s %s" % (type_dict[a.ctype]["jn_type"], a.name.replace(".","_").replace("[","").replace("]","")) for a in jn_args])
A
Andrey Kamaev 已提交
722 723 724
            ) );

            # java part:
725 726 727 728 729 730 731 732 733

            #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 已提交
734 735 736 737
            # 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 );  }
738 739 740
            ret_val = type_dict[fi.ctype]["j_type"] + " retVal = "
            tail = ""
            ret = "return retVal;"
A
Andrey Kamaev 已提交
741
            if fi.ctype == "void":
742 743
                ret_val = ""
                ret = "return;"
A
Andrey Kamaev 已提交
744
            elif fi.ctype == "": # c-tor
745 746
                ret_val = "nativeObj = "
                ret = "return;"
A
Andrey Kamaev 已提交
747
            elif fi.ctype in self.classes: # wrapped class
748 749
                ret_val = type_dict[fi.ctype]["j_type"] + " retVal = new " + self.classes[fi.ctype].jname + "("
                tail = ")"
750
            elif "jn_type" not in type_dict[fi.ctype]:
751 752
                ret_val = type_dict[fi.ctype]["j_type"] + " retVal = new " + type_dict[fi.ctype]["j_type"] + "("
                tail = ")"
A
Andrey Kamaev 已提交
753 754 755 756 757 758

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

            self.java_code.write( Template(\
759 760 761 762 763 764 765
"""${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 已提交
766

767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782
"""
                ).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 已提交
783 784

            # cpp part:
785 786
            # jni_func(..) { _retval_ = cv_func(..); return _retval_; }
            ret = "return _retval_;"
787
            default = "return 0;"
A
Andrey Kamaev 已提交
788
            if fi.ctype == "void":
789 790 791 792
                ret = "return;"
                default = "return;"
            elif not fi.ctype: # c-tor
                ret = "return (jlong) _retval_;"
793
            elif fi.ctype == "string":
794
                ret = "return env->NewStringUTF(_retval_.c_str());"
795
                default = 'return env->NewStringUTF("");'
796
            elif fi.ctype in self.classes: # wrapped class:
797
                ret = "return (jlong) new %s(_retval_);" % fi.ctype
798
            elif type_dict[fi.ctype]["jni_type"] == "jdoubleArray":
799
                ret = "return _da_retval_;"
A
Andrey Kamaev 已提交
800 801

            cvname = "cv::" + fi.name
802
            #j2cvargs = []
803 804 805
            retval = fi.ctype + " _retval_ = "
            if fi.ctype == "void":
                retval = ""
A
Andrey Kamaev 已提交
806 807
            if fi.classname:
                if not fi.ctype: # c-tor
808 809
                    retval = fi.classname + "* _retval_ = "
                    cvname = "new " + fi.classname
A
Andrey Kamaev 已提交
810
                elif fi.static:
811
                    cvname = "%s::%s" % (fi.classname, fi.name)
A
Andrey Kamaev 已提交
812
                else:
813
                    cvname = "me->" + fi.name
814
                    c_prologue.append(\
815
                        "%(cls)s* me = (%(cls)s*) self; //TODO: check for NULL" \
816
                            % { "cls" : fi.classname} \
A
Andrey Kamaev 已提交
817 818 819
                    )
            cvargs = []
            for a in args:
820
                cvargs.append( type_dict[a.ctype].get("jni_name", "%(n)s") % {"n" : a.name})
821 822
                if "vector" not in a.ctype and "jni_var" in type_dict[a.ctype]: # complex type
                    c_prologue.append(type_dict[a.ctype]["jni_var"] % {"n" : a.name} + ";")
A
Andrey Kamaev 已提交
823

824
            rtype = type_dict[fi.ctype].get("jni_type", "jdoubleArray")
A
Andrey Kamaev 已提交
825 826 827 828 829 830
            self.cpp_code.write ( Template( \
"""

JNIEXPORT $rtype JNICALL Java_org_opencv_${module}_$fname
  ($args)
{
831
    try {
832 833 834
#ifdef DEBUG
        LOGD("$module::$fname()");
#endif // DEBUG
835
        $prologue
836
        $retval$cvname( $cvargs );
837
        $epilogue
838
        $ret
839
    } catch(cv::Exception e) {
840 841 842
#ifdef DEBUG
        LOGD("$module::$fname() catched cv::Exception: %s", e.what());
#endif // DEBUG
843 844 845
        jclass je = env->FindClass("org/opencv/CvException");
        if(!je) je = env->FindClass("java/lang/Exception");
        env->ThrowNew(je, e.what());
846
        $default
847
    } catch (...) {
848 849 850
#ifdef DEBUG
        LOGD("$module::$fname() catched unknown exception (...)");
#endif // DEBUG
851 852
        jclass je = env->FindClass("java/lang/Exception");
        env->ThrowNew(je, "Unknown exception in JNI code {$module::$fname()}");
853
        $default
854
    }
A
Andrey Kamaev 已提交
855 856
}

857

A
Andrey Kamaev 已提交
858 859 860 861
""" ).substitute( \
        rtype = rtype, \
        module = self.module, \
        fname = fi.jni_name + ["",suffix][isoverload], \
862
        args = ", ".join(["%s %s" % (type_dict[a.ctype].get("jni_type"), a.name) for a in jni_args]), \
863 864
        prologue = "\n        ".join(c_prologue), \
        epilogue = "  ".join(c_epilogue), \
A
Andrey Kamaev 已提交
865 866 867
        ret = ret, \
        cvname = cvname, \
        cvargs = ", ".join([a for a in cvargs]), \
868 869
        default = default, \
        retval = retval, \
A
Andrey Kamaev 已提交
870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887
    ) )

            # 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:
888
                self.gen_func(fi, len(ffi.funcs)>1, self.jn_code)
A
Andrey Kamaev 已提交
889 890 891 892


    def gen_classes(self):
        # generate code for the classes (their methods and consts)
893 894
        indent = " " * 4
        indent_m = indent + " " * 4
A
Andrey Kamaev 已提交
895 896 897
        classlist = self.classes.items()
        classlist.sort()
        for name, ci in classlist:
898
            if name == "Mat":
899 900
                continue
            self.java_code.write( "\n\n" + indent + "// C++: class %s" % (ci.cname) + "\n" )
901
            self.java_code.write( indent + "//javadoc: " + name + "\n" ) #java doc comment
A
Andrey Kamaev 已提交
902 903 904 905 906 907 908
            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:
909
                prefix = "\n" + indent_m + "\t"
A
Andrey Kamaev 已提交
910 911 912
                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 )
913 914
            # methods
            jn_code = StringIO()
A
Andrey Kamaev 已提交
915 916 917 918 919 920
            # c-tors
            fflist = ci.methods.items()
            fflist.sort()
            for n, ffi in fflist:
                if ffi.isconstructor:
                    for fi in ffi.funcs:
921
                        self.gen_func(fi, len(ffi.funcs)>1, jn_code)
A
Andrey Kamaev 已提交
922 923 924 925
            self.java_code.write( "\n" )
            for n, ffi in fflist:
                if not ffi.isconstructor:
                    for fi in ffi.funcs:
926
                        self.gen_func(fi, len(ffi.funcs)>1, jn_code)
A
Andrey Kamaev 已提交
927

928 929 930 931 932 933 934 935 936 937 938 939 940
            # 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")
941
            self.java_code.write(indent_m + 'static { System.loadLibrary("opencv_java"); }\n')
942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966
            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 已提交
967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988


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)