File: gen3_julia_cxx.py

package info (click to toggle)
opencv 4.10.0%2Bdfsg-5
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 282,092 kB
  • sloc: cpp: 1,178,079; xml: 682,621; python: 49,092; lisp: 31,150; java: 25,469; ansic: 11,039; javascript: 6,085; sh: 1,214; cs: 601; perl: 494; objc: 210; makefile: 173
file content (244 lines) | stat: -rwxr-xr-x 9,596 bytes parent folder | download | duplicates (2)
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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
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
240
241
242
243
244
#!/usr/bin/env python

# This file is part of OpenCV project.
# It is subject to the license terms in the LICENSE file found in the top-level directory
# of this distribution and at http://opencv.org/license.html
# Copyright (C) 2020 by Archit Rungta

from __future__ import unicode_literals # Needed for python2

import hdr_parser, sys, re, os
from string import Template
from pprint import pprint
from collections import namedtuple
if sys.version_info[0] >= 3:
    from io import StringIO
else:
    from cStringIO import StringIO
import os, shutil

from parse_tree import *


jl_cpp_argmap = {}
jl_cpp_defmap = {}
julia_types = ["Int32", "Float32", "Float64", "Bool", "String", "Array", "Any"]
cv_types = ["UMat","Size" ]

submodule_template = Template('')
root_template = Template('')
with open("binding_templates_jl/template_cv2_submodule_cxx.jl", "r") as f:
    submodule_template = Template(f.read())
with open("binding_templates_jl/template_cv2_root.jl", "r") as f:
    root_template = Template(f.read())
with open("typemap.txt", 'r') as f:
    tmp = f.readlines()
    for ln in tmp:
        ln = ln.strip('\n').split(':')
        jl_cpp_argmap[ln[0]] = ln[1]
with open("defval.txt", 'r') as f:
    tmp = f.readlines()
    for ln in tmp:
        ln = ln.strip('\n').split('|')
        if ln[0] not in jl_cpp_defmap:
            jl_cpp_defmap[ln[0]] = {}
        jl_cpp_defmap[ln[0]][ln[1]] = ln[2]


def handle_def_arg(inp, tp = '', ns=''):
    tp = tp.strip()
    inp = inp.strip()

    out = ''

    if inp in jl_cpp_defmap[tp]:
        out = jl_cpp_defmap[tp][inp]
    elif inp != '':
        print(inp+" not found")
    # print(inp, tp, out)
    return out

def handle_jl_arg(inp):
    if not inp:
        return ''
    inp = inp.replace('std::', '')
    if inp in jl_cpp_argmap:
        return jl_cpp_argmap[inp]
    inp = inp.replace('cv::', '')
    return inp
    # return outs

class ClassInfo(ClassInfo):

    def get_jl_code(self):

        if self.ismap:
            return ''
        return self.overload_get()+self.overload_set()

    def overload_get(self):
        stra = "function Base.getproperty(m::%s, s::Symbol)\n" %(self.mapped_name)
        if self.isalgorithm:
            stra = "function Base.getproperty(m::cv_Ptr{%s}, s::Symbol)\n" %(self.mapped_name)
        for prop in self.props:
            stra = stra + "    if s==:" + prop.name+"\n"
            stra = stra + "        return cpp_to_julia(%s(m))\n"%self.get_prop_func_cpp("get", prop.name)
            stra = stra + "    end\n"
        stra = stra + "    return Base.getfield(m, s)\nend\n"
        return stra

    def overload_set(self):

        stra = "function Base.setproperty!(m::%s, s::Symbol, v)\n" %(self.mapped_name)
        if self.isalgorithm:
            stra = "function Base.setproperty!(m::cv_Ptr{%s}, s::Symbol, v)\n" %(self.mapped_name)

        for prop in self.props:
            if not prop.readonly:
                continue
            stra = stra + "    if s==:" + prop.name+"\n"
            stra = stra + "        %s(m, julia_to_cpp(v))\n"%(self.get_prop_func_cpp("set", prop.name))
            stra = stra + "    end\n"
        stra = stra + "    return Base.setfield!(m, s, v)\nend\n"
        return stra

class FuncVariant(FuncVariant):

    def promote_type(self, tp):
        if tp=='int':
            return 'long long'
        elif tp =='float':
            return 'double'
        return tp


    def get_argument_full(self, classname='', isalgo = False):
        arglist = self.inlist + self.optlist

        argnamelist = [arg.name+"::"+(handle_jl_arg(self.promote_type(arg.tp)) if handle_jl_arg(arg.tp) not in pass_by_val_types else handle_jl_arg(self.promote_type(arg.tp[:-1]))) for arg in arglist]
        argstr = ", ".join(argnamelist)
        return argstr

    def get_argument_opt(self, ns=''):
        # [print(arg.default_value,":",handle_def_arg(arg.default_value, handle_jl_arg(arg.tp))) for arg in self.optlist]
        try:
            str2 =  ", ".join(["%s::%s = %s(%s)" % (arg.name, handle_jl_arg(self.promote_type(arg.tp)), handle_jl_arg(self.promote_type(arg.tp)) if (arg.tp == 'int' or arg.tp=='float' or arg.tp=='double') else '', handle_def_arg(arg.default_value, handle_jl_arg(self.promote_type(arg.tp)), ns)) for arg in self.optlist])
            return str2
        except KeyError:
            return ''

    def get_argument_def(self, classname, isalgo):
        arglist = self.inlist
        argnamelist = [arg.name+"::"+(handle_jl_arg(self.promote_type(arg.tp)) if handle_jl_arg(self.promote_type(arg.tp)) not in pass_by_val_types else handle_jl_arg(self.promote_type(arg.tp[:-1]))) for arg in arglist]
        argstr = ", ".join(argnamelist)
        return argstr

    def get_return(self, classname=''):
        argstr = ''
        arglist = self.inlist + self.optlist
        return "return cpp_to_julia(%s(%s))" %(self.get_wrapper_name(), ",".join(["julia_to_cpp(%s)" % (x.name) for x in arglist]))

    def get_algo_tp(self, classname, isalgo):
        if not isalgo or not classname:
            return ''
        return ' where {T <: %s}' % classname

    def get_complete_code(self, classname='', isalgo = False, iscons = False, gen_default = True, ns = ''):
        if classname and not iscons:
            if isalgo:
                self.inlist = [ArgInfo("cobj", "cv_Ptr{T}")] + self.inlist
            else:
                self.inlist = [ArgInfo("cobj", classname)] + self.inlist
        map_name = self.mapped_name
        if ns!='cv':
            map_name = '%s_%s' %(ns.split('::')[-1], map_name)
        outstr = 'function %s(%s)%s\n\t%s\nend\n' % (map_name, self.get_argument_full(classname, isalgo), self.get_algo_tp(classname, isalgo),self.get_return())


        str2 = ", ".join([x.name for x  in self.inlist + self.optlist])
        # outstr = outstr +
        if self.get_argument_opt() != '' and gen_default:
            outstr = outstr + ('%s(%s; %s)%s = %s(%s)\n' % (map_name, self.get_argument_def(classname, isalgo), self.get_argument_opt(ns), self.get_algo_tp(classname, isalgo), map_name, str2))

        if iscons and len(self.inlist+self.optlist)==0 and ns=='cv':
            return ''

        return outstr



def gen(srcfiles):
    namespaces, _ = gen_tree(srcfiles)

    jl_code = StringIO()
    for name, ns in namespaces.items():
        cv_types.extend(ns.registered)
        jl_code = StringIO()
        nsname = name
        for e1,e2 in ns.enums.items():
            # jl_code.write('\n   const {0} = Int32'.format(e2[0]))
            jl_code.write('\n   const {0} = Int64 \n'.format(e2[0].replace("cv::", "").replace("::", "_")))

        # Do not duplicate functions. This should prevent overwriting of Mat function by UMat functions
        function_signatures = []
        for cname, cl in ns.classes.items():
            cl.__class__ = ClassInfo
            jl_code.write(cl.get_jl_code())
            for mname, fs in cl.methods.items():
                for f in fs:
                    f.__class__ = FuncVariant
                    sign = (f.name, f.mapped_name, f.classname, [x.tp for x in f.inlist+f.optlist])
                    if sign in function_signatures:
                        print("Skipping entirely: ", f.name)
                        continue
                    sign2 = (f.name, f.mapped_name, f.classname, [x.tp for x in f.inlist])
                    gend = True
                    if sign2 in function_signatures:
                        print("Skipping default declaration: ", f.name)
                        gend = False
                    jl_code.write('\n%s'  % f.get_complete_code(classname = cl.mapped_name, isalgo = cl.isalgorithm, gen_default = gend, ns=nsname))
                    function_signatures.append(sign)
                    function_signatures.append(sign2)
            for f in cl.constructors:
                f.__class__ = FuncVariant
                jl_code.write('\n%s'  % f.get_complete_code(classname = cl.mapped_name, isalgo = cl.isalgorithm, iscons = True, ns=nsname))
        for mname, fs in ns.funcs.items():
            for f in fs:
                f.__class__ = FuncVariant
                sign = (f.name, f.mapped_name, f.classname, [x.tp for x in f.inlist+f.optlist])
                if sign in function_signatures:
                    print("Skipping entirely: ", f.name)
                    continue
                gend = True
                sign2 = (f.name, f.mapped_name, f.classname, [x.tp for x in f.inlist])
                if sign2 in function_signatures:
                    print("Skipping default declaration: ", f.name)
                    gend = False

                jl_code.write('\n%s' % f.get_complete_code(gen_default = gend, ns=nsname))
                function_signatures.append(sign)
                function_signatures.append(sign2)


        imports = ''
        for namex in namespaces:
            if namex.startswith(name) and len(namex.split('::')) == 1 + len(name.split('::')):
                imports = imports + '\ninclude("%s_cxx_wrap.jl")'%namex.replace('::', '_')
        code = ''
        if name == 'cv':
            code = root_template.substitute(modname = name, code = jl_code.getvalue(), submodule_imports = imports)
        else:
            code = submodule_template.substitute(code = jl_code.getvalue(), submodule_imports = imports)

        with open ('autogen_jl/%s_cxx_wrap.jl' % ns.name.replace('::', '_'), 'w') as fd:
            fd.write(code)





srcfiles = hdr_parser.opencv_hdr_list
if len(sys.argv) > 1:
    srcfiles = [l.strip() for l in sys.argv[1].split(';')]

gen(srcfiles)