extract_macros.py 5.44 KB
Newer Older
1 2 3 4 5 6 7 8 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 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 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 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
#! /usr/bin/env python
"""
This script extracts macros functions from the OpenCV headers and attempts to generate
standard C function prototypes.  Type information is missing in the macros, so SWIG 
cannot generate C code for them unless we provide this.  
"""

import sys, re

ARG_MAP = { 
    "mat":"CvMat*",   
    "type":"int", 
    "flags":"int",
    "img":"CvArr *", 
    "image":"IplImage *", 
    "mat1":"CvMat*", 
    "mat2":"CvMat*",
    "seq":"CvSeq*",
    "elem_ptr":"void *",
    "elem":"CvPoint",
    "elem_type":"ignore",
    "elemtype":"ignore",
    "elem_size":"int",
    "edge":"CvGraphEdge *",
    "vertex":"CvGraphVtx *",
    "contour":"CvSeq *",
    "vtx":"CvGraphVtx *",
    "reader":"CvSeqReader",
    "writer":"CvSeqWriter",
    "hist":"CvHistogram *",
    "ptr":"void *",
    "arr":"CvArr *",
    "header":"CvMat *",
    "src":"CvArr *",
    "src1":"CvArr *",
    "src2":"CvArr *",
    "src3":"CvArr *",
    "dst":"CvArr *",
    "pt1":"CvPoint",
    "pt2":"CvPoint",
    "_pt":"CvPoint",
    "index":"int",
    "idx":"int",
    "set":"CvSet *",
    "n":"int",
    "a":"int",
    "b":"int",
    "t":"int",
    "value":"double",
    "row":"int",
    "col":"int",
    "cn":"int",
    "new_cn":"int",
    "pix_size":"int",
    "depth":"int",
    "node":"CvSparseNode *",
    "storage":"CvMemStorage *",
    "new_dims": "int",
    "new_sizes": "int *",
    "A":"CvArr *",
    "B":"CvArr *",
    "C":"CvArr *",
    "real_scalar":"double",
    "graph":"CvGraph *",
    "r":"double",
    "g":"double",
#    "b":"double",
    "line_iterator":"CvLineIterator",
    "deltas":"double *",
    "step":"int",
    "haar":"void *",
#    "contour":"const void*",  # handled as a special case in cvshadow
    "range":"CvSize", 
    "nch":"int",
    "method":"int",
    "factor":"double"
}
RET_MAP = {
    "cvContourPerimeter":"double",
    "CV_RGB":"CvScalar",
    "CV_NEXT_GRAPH_EDGE":"CvGraphEdge *",
    "CV_IMIN":"int",
    "CV_IMAX":"int",
    "CV_IABS":"int",
    "CV_MAT_CN":"int",
    "CV_MAT_DEPTH":"int",
    "CV_NEXT_LINE_POINT":"void",
}

# special cases
MACROS = {
    #"CV_MAKETYPE":"",  # SWIG 1.3.29 doesn't like this one for some indeterminant reason
    "CV_TURN_ON_IPL_COMPATIBILITY":"",
    "CV_MAT_ELEM_PTR_FAST":"void * CV_MAT_ELEM_PTR_FAST(CvMat mat,int row,int col,int pix_size);",
    "CV_MAT_ELEM_PTR":"void * CV_MAT_ELEM_PTR(CvMat mat,int row,int col);",
    "CV_NODE_VAL":"void * CV_NODE_VAL(CvSparseMat* mat,CvSparseNode * node);",
    "CV_NODE_IDX":"int * CV_NODE_IDX(CvSparseMat* mat,CvSparseNode * node);",
    "CV_READ_CHAIN_POINT":"void CV_READ_CHAIN_POINT(CvPoint _pt, CvChainPtReader reader);",
    "CV_SUBDIV2D_NEXT_EDGE":"CvQuadEdge2D* CV_SUBDIV2D_NEXT_EDGE(CvSubdiv2DEdge edge);",
    "cvFree":"void cvFree(void ** ptr);",
    

}

print """
/*//////////////////////////////////////////////////////////////////////////////////////////////////
// This file is automatically generated from the extract_macros.py script found in the 'utils'
// subdirectory of the OpenCV distribution.  If the generated function prototypes are missing or 
// incorrect, it is likely that a name->type mapping will have to be added to the script 
/////////////////////////////////////////////////////////////////////////////////////////////////M*/
"""

print "// This file was generated from the following header files: "
print "// %s" % "\n// ".join(sys.argv[1:])


def determine_return_type(name, arguments):
    if RET_MAP.has_key( name ):
        return RET_MAP[name]
    if name.find("_IS_")>=0 or \
       name.find("_HAS_")>=0 or \
       name.find("_KIND")>=0 or \
       name.find("_ARE_")>=0 or \
       name.find("_SIZE")>=0 or \
       name.find("Idx")>=0 or \
       name.find("Count")>=0 or \
       (name.find("TYPE")>=0 and not name.find("TYPES")>=0):
        return "int"
    if re.match( r"CV_(?:8|16|32|64)(?:U|S|F)C", name ):
        return "int"
    if len(arguments) is 1 and arguments[0].startswith("double"):
        return "double"
    if name.find("_PTR")>=0:
        return "void *"
    if name.endswith("POINT"):
        return "CvPoint"
    return "void"

for m in MACROS:
    print MACROS[m]

for fn in sys.argv[1:]:
    f = open( fn, "r" )
    in_define = False
    fstr=""
    macro_name=""
    for l in f.xreadlines():
        m = re.match( r"^#define\s+((?:CV_|IPL_|cv)\w+)\s*\(([_, a-zA-Z0-9]*)\)\s*(.*)", l )

        if m and not m.group(1).endswith("FIELDS") and not MACROS.has_key(m.group(1)):
            macro_name = m.group(1)
            args = m.group(2).strip().split(",")
            
            # assign return type
            ret=determine_return_type( macro_name, args )

            # assign type to each argument
            no_args = len(args) is 0
            typed_args = []
            ignore = False
            for arg in args:
                arg = arg.strip()
                if len(arg) is 0:
                    no_args = True
                    break
                if ARG_MAP.has_key( arg ):
                    if ARG_MAP[arg] is "ignore":
                        ignore=True
                        break
                    typed_args.append( "%s %s"%( ARG_MAP[arg], arg ) )
                else:
                    sys.stderr.write( "\"%s\":\"?\", in macro '%s'\n" % (arg, macro_name) )
                    typed_args = []
                    break
            if not ignore and (no_args or len(typed_args)>0):
                decl = "%s %s(%s);" % (ret, macro_name, ",".join( typed_args) )
                MACROS[ macro_name ] = decl
                print decl

    f.close()