Commit f45bc356 authored by hbristow's avatar hbristow

input/output assignment in templates is working for non-trivial cases. Updated…

input/output assignment in templates is working for non-trivial cases. Updated parse_tree to handle '/IO' and '/S' modifiers
parent 1a15ed32
...@@ -7,11 +7,10 @@ def inputs(args): ...@@ -7,11 +7,10 @@ def inputs(args):
In OpenCV input arguments are all arguments with names In OpenCV input arguments are all arguments with names
not beginning with 'dst' not beginning with 'dst'
''' '''
out = [] try:
for arg in args: return [arg for arg in args['only'] if arg.I and not arg.O]
if not arg.name.startswith('dst'): except:
out.append(arg) return [arg for arg in args if arg.I]
return out
def ninputs(args): def ninputs(args):
'''Counts the number of input arguments in the input list''' '''Counts the number of input arguments in the input list'''
...@@ -22,15 +21,24 @@ def outputs(args): ...@@ -22,15 +21,24 @@ def outputs(args):
reference, and returns a list of only those elements. reference, and returns a list of only those elements.
In OpenCV, output references are preceeded by 'dst' In OpenCV, output references are preceeded by 'dst'
''' '''
out = [] try:
for arg in args: return [arg for arg in args['only'] if arg.O and not arg.I]
if arg.name.startswith('dst'): except:
out.append(arg) return [arg for arg in args if arg.O]
return out
def only(args):
'''Returns exclusively the arguments which are only inputs
or only outputs'''
d = {};
d['only'] = args
return d
def void(arg):
return arg == 'void'
def flip(arg):
return not arg
def output(arg):
return True if arg.name.startswith('dst') else False
def noutputs(args): def noutputs(args):
'''Counts the number of output arguments in the input list''' '''Counts the number of output arguments in the input list'''
return len(outputs(args)) return len(outputs(args))
......
...@@ -32,10 +32,13 @@ class MatlabWrapperGenerator(object): ...@@ -32,10 +32,13 @@ class MatlabWrapperGenerator(object):
jtemplate.filters['toUnderCase'] = toUnderCase jtemplate.filters['toUnderCase'] = toUnderCase
jtemplate.filters['comment'] = comment jtemplate.filters['comment'] = comment
jtemplate.filters['inputs'] = inputs jtemplate.filters['inputs'] = inputs
jtemplate.filters['ninputs'] = ninputs
jtemplate.filters['outputs'] = outputs jtemplate.filters['outputs'] = outputs
jtemplate.filters['output'] = output
jtemplate.filters['noutputs'] = noutputs jtemplate.filters['noutputs'] = noutputs
jtemplate.filters['ninputs'] = ninputs jtemplate.filters['only'] = only
jtemplate.filters['void'] = void
jtemplate.filters['not'] = flip
# load the templates # load the templates
tfunction = jtemplate.get_template('template_function_base.cpp') tfunction = jtemplate.get_template('template_function_base.cpp')
......
...@@ -65,6 +65,7 @@ class Translator(object): ...@@ -65,6 +65,7 @@ class Translator(object):
name = self.translateName(defn[0]) name = self.translateName(defn[0])
clss = self.translateClassName(defn[0]) clss = self.translateClassName(defn[0])
rtp = defn[1] rtp = defn[1]
static = True if 'S' in ''.join(defn[2]) else False
args = defn[3] args = defn[3]
req = [] req = []
opt = [] opt = []
...@@ -72,7 +73,7 @@ class Translator(object): ...@@ -72,7 +73,7 @@ class Translator(object):
if arg: if arg:
a = self.translateArgument(arg) a = self.translateArgument(arg)
opt.append(a) if a.default else req.append(a) opt.append(a) if a.default else req.append(a)
return Function(name, clss, '', rtp, False, req, opt) return Function(name, clss, static, '', rtp, False, req, opt)
def translateConstant(self, defn): def translateConstant(self, defn):
const = True if 'const' in defn[0] else False const = True if 'const' in defn[0] else False
...@@ -83,10 +84,16 @@ class Translator(object): ...@@ -83,10 +84,16 @@ class Translator(object):
return Constant(name, clss, tp, const, '', val) return Constant(name, clss, tp, const, '', val)
def translateArgument(self, defn): def translateArgument(self, defn):
tp = defn[0] ref = '*' if '*' in defn[0] else ''
ref = '&' if '&' in defn[0] else ref
const = ' const ' in ' '+defn[0]+' '
tp = " ".join([word for word in defn[0].replace(ref, '').split() if not ' const ' in ' '+word+' '])
name = defn[1] name = defn[1]
default = defn[2] if defn[2] else '' default = defn[2] if defn[2] else ''
return Argument(name, tp, False, '', default) modifiers = ''.join(defn[3])
I = True if not modifiers or 'I' in modifiers else False
O = True if 'O' in modifiers else False
return Argument(name, tp, const, I, O, ref, default)
def translateName(self, name): def translateName(self, name):
return name.split(' ')[-1].split('.')[-1] return name.split(' ')[-1].split('.')[-1]
...@@ -123,9 +130,10 @@ class Class(object): ...@@ -123,9 +130,10 @@ class Class(object):
(join((f.__str__() for f in self.functions), '\n\t') if self.functions else '')+'\n};' (join((f.__str__() for f in self.functions), '\n\t') if self.functions else '')+'\n};'
class Function(object): class Function(object):
def __init__(self, name='', clss='', namespace='', rtp='', const=False, req=None, opt=None): def __init__(self, name='', clss='', static=False, namespace='', rtp='', const=False, req=None, opt=None):
self.name = name self.name = name
self.clss = clss self.clss = clss
self.static = static
self.const = const self.const = const
self.namespace = namespace self.namespace = namespace
self.rtp = rtp self.rtp = rtp
...@@ -138,10 +146,12 @@ class Function(object): ...@@ -138,10 +146,12 @@ class Function(object):
')'+(' const' if self.const else '')+';' ')'+(' const' if self.const else '')+';'
class Argument(object): class Argument(object):
def __init__(self, name='', tp='', const=False, ref='', default=''): def __init__(self, name='', tp='', const=False, I=True, O=False, ref='', default=''):
self.name = name self.name = name
self.tp = tp self.tp = tp
self.ref = ref self.ref = ref
self.I = I
self.O = O
self.const = const self.const = const
self.default = default self.default = default
......
// compose a function /*
{% macro compose(fun, retname="ret") %} * compose
{%- if not fun.rtp == "void" -%} {{fun.rtp}} retname = {% endif -%} * compose a function call
{{fun.name}}( * This macro takes as input a Function object and composes
* a function call by inspecting the types and argument names
*/
/
{% macro compose(fun) %}
{# ----------- Return type ------------- #}
{%- if not fun.rtp|void -%} {{fun.rtp}} retval = {% endif -%}
cv::{{fun.name}}(
{#- ----------- Required ------------- -#}
{%- for arg in fun.req -%} {%- for arg in fun.req -%}
{%- if arg.ref == '*' -%}&{%- endif -%}
{{arg.name}} {{arg.name}}
{%- if not loop.last %}, {% endif %} {%- if not loop.last %}, {% endif %}
{% endfor %} {% endfor %}
{#- ----------- Optional ------------- -#}
{% if fun.req and fun.opt %}, {% endif %} {% if fun.req and fun.opt %}, {% endif %}
{%- for opt in fun.opt -%} {%- for opt in fun.opt -%}
{%- if opt.ref == '*' -%}&{%- endif -%}
{{opt.name}} {{opt.name}}
{%- if not loop.last -%}, {% endif %} {%- if not loop.last -%}, {% endif %}
{%- endfor -%} {%- endfor -%}
...@@ -18,19 +29,18 @@ ...@@ -18,19 +29,18 @@
{%- macro generate(fun) -%} {%- macro generate(fun) -%}
// unpack the arguments // unpack the arguments
// inputs {# ----------- Inputs ------------- #}
{% for arg in fun.req|inputs %} {% for arg in fun.req|inputs %}
{{arg.tp}} {{arg.name}} = inputs[{{ loop.index0 }}]; {{arg.tp}} {{arg.name}} = inputs[{{ loop.index0 }}];
{% endfor %} {% endfor %}
{% for opt in fun.opt|inputs %} {% for opt in fun.opt|inputs %}
{{opt.tp}} {{opt.name}} = (nrhs > {{loop.index0 + fun.req|ninputs}}) ? inputs[{{loop.index0 + fun.req|ninputs}}] : {{opt.default}}; {{opt.tp}} {{opt.name}} = (nrhs > {{loop.index0 + fun.req|inputs|length}}) ? inputs[{{loop.index0 + fun.req|inputs|length}}] : {{opt.default}};
{% endfor %} {% endfor %}
{# ----------- Outputs ------------ #}
// outputs {% for arg in fun.req|only|outputs %}
{% for arg in fun.req|outputs %}
{{arg.tp}} {{arg.name}}; {{arg.tp}} {{arg.name}};
{% endfor %} {% endfor %}
{% for opt in fun.opt|outputs %} {% for opt in fun.opt|only|outputs %}
{{opt.tp}} {{opt.name}}; {{opt.tp}} {{opt.name}};
{% endfor %} {% endfor %}
...@@ -47,11 +57,14 @@ ...@@ -47,11 +57,14 @@
} }
// assign the outputs into the bridge // assign the outputs into the bridge
{% if not fun.rtp|void %}
outputs[0] = retval;
{% endif %}
{% for arg in fun.req|outputs %} {% for arg in fun.req|outputs %}
outputs[{{loop.index0}}] = {{arg.name}}; outputs[{{loop.index0 + fun.rtp|void|not}}] = {{arg.name}};
{% endfor %} {% endfor %}
{% for opt in fun.opt|outputs %} {% for opt in fun.opt|outputs %}
outputs[{{loop.index0 + fun.req|noutputs}}] = {{opt.name}}; outputs[{{loop.index0 + fun.rtp|void|not + fun.req|outputs|length}}] = {{opt.name}};
{% endfor %} {% endfor %}
{%- endmacro -%} {%- endmacro -%}
...@@ -13,14 +13,13 @@ ...@@ -13,14 +13,13 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <exception> #include <exception>
#include <opencv2/{{ns}}.hpp> #include <opencv2/{{includes}}.hpp>
{% block includes %} {% block includes %}
{% endblock %} {% endblock %}
using namespace std;
using namespace cv;
/* /*
* {{ fun.name }} * {{ fun.name }}
* {{ fun }}
* Gateway routine * Gateway routine
* nlhs - number of return arguments * nlhs - number of return arguments
* plhs - pointers to return arguments * plhs - pointers to return arguments
...@@ -31,15 +30,13 @@ void mexFunction(int nlhs, mxArray* plhs[], ...@@ -31,15 +30,13 @@ void mexFunction(int nlhs, mxArray* plhs[],
int nrhs, const mxArray* prhs[]) { int nrhs, const mxArray* prhs[]) {
// assertions // assertions
mxAssert(nrhs >= {{fun.req|length - fun.req|noutputs}}, "Too few required input arguments specified"); mxAssert(nrhs >= {{fun.req|length - fun.req|outputs|length}}, "Too few required input arguments specified");
mxAssert(nrhs <= {{fun.req|length + fun.opt|length - fun.req|noutputs - fun.opt|noutputs}}, "Too many input arguments specified"); mxAssert(nrhs <= {{fun.req|length + fun.opt|length - fun.req|outputs|length - fun.opt|outputs|length}}, "Too many input arguments specified");
mxAssert(nlhs <= {{fun.ret|length + fun.req|noutputs + fun.opt|noutputs}}, "Too many output arguments specified"); mxAssert(nlhs <= {{ fun.rtp|void|not + fun.req|outputs|length + fun.opt|outputs|length}}, "Too many output arguments specified");
// setup // setup
vector<Bridge> inputs(plhs, plhs+nrhs); std::vector<Bridge> inputs(plhs, plhs+nrhs);
vector<Bridge> outputs(nlhs); std::vector<Bridge> outputs(nlhs);
{{ fun }}
{{ functional.generate(fun) }} {{ functional.generate(fun) }}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment