summaryrefslogtreecommitdiff
path: root/gr-utils/bindtool/templates/generic_python_cc.mako
diff options
context:
space:
mode:
Diffstat (limited to 'gr-utils/bindtool/templates/generic_python_cc.mako')
-rw-r--r--gr-utils/bindtool/templates/generic_python_cc.mako221
1 files changed, 221 insertions, 0 deletions
diff --git a/gr-utils/bindtool/templates/generic_python_cc.mako b/gr-utils/bindtool/templates/generic_python_cc.mako
new file mode 100644
index 0000000000..a4743fb8fb
--- /dev/null
+++ b/gr-utils/bindtool/templates/generic_python_cc.mako
@@ -0,0 +1,221 @@
+##
+## Copyright 2020 Free Software Foundation, Inc.
+##
+## This file is part of GNU Radio
+##
+## SPDX-License-Identifier: GPL-3.0-or-later
+##
+##
+<%
+ namespace = header_info['namespace']
+ modname = header_info['module_name']
+ header_filename = header_info['filename']
+ header_file_hash = header_info['md5hash']
+%>\
+${license}
+
+/***********************************************************************************/
+/* This file is automatically generated using bindtool and can be manually edited */
+/* The following lines can be configured to regenerate this file during cmake */
+/* If manual edits are made, the following tags should be modified accordingly. */
+/* BINDTOOL_GEN_AUTOMATIC(${'1' if flag_automatic else '0'}) */
+/* BINDTOOL_USE_PYGCCXML(${'1' if flag_pygccxml else '0'}) */
+/* BINDTOOL_HEADER_FILE(${header_filename}) */
+/* BINDTOOL_HEADER_FILE_HASH(${header_file_hash}) */
+/***********************************************************************************/
+
+#include <pybind11/complex.h>
+#include <pybind11/pybind11.h>
+#include <pybind11/stl.h>
+
+namespace py = pybind11;
+
+#include <${prefix_include_root}/${basename}.h>
+// pydoc.h is automatically generated in the build directory
+#include <${basename}_pydoc.h>
+
+void bind_${basename}(py::module& m)
+{
+${render_namespace(namespace=namespace,modname=[modname],modvar='m')}
+}
+
+<%def name='render_constructor()' >
+</%def>
+
+<%def name='render_function(fcn,fcn_list,cls_name,filter_val,isfree=False,modvar="",doc_prefix="")' >
+<%
+fcn_args = fcn['arguments']
+fcn_name = fcn['name']
+has_static = fcn['has_static'] if 'has_static' in fcn else False
+matcher = lambda x,name: x['name'] == name
+matched_list = [f for f in fcn_list if matcher(f,fcn_name)]
+overloaded = len(matched_list) > 1
+overloaded_str = ''
+index_str = ''
+if overloaded:
+ index_into_list = matched_list.index(fcn)
+ index_str = ','+str(index_into_list)
+ overloaded_str = '({} ({}::*)({}))'.format(fcn['return_type'],cls_name,', '.join([f['dtype'] for f in fcn_args]))
+%>\
+% if fcn['name'] != filter_val:
+ ${modvar if isfree else ""}${".def_static" if has_static and not isfree else ".def"}("${fcn['name']}",${overloaded_str}&${cls_name}::${fcn['name']},
+% for arg in fcn_args:
+ py::arg("${arg['name']}")${" = " + arg['default'] if arg['default'] else ''},
+% endfor ## args
+ D(${doc_prefix}${cls_name},${fcn['name']}${index_str})
+ )${';' if isfree else ""}
+% endif ## Not a filtered function name
+</%def>
+
+<%def name='render_free_function(fcn,fcn_list,namespace_name,filter_val,modvar="",doc_prefix="")' >
+<%
+fcn_args = fcn['arguments']
+fcn_name = fcn['name']
+has_static = fcn['has_static'] if 'has_static' in fcn else False
+matcher = lambda x,name: x['name'] == name
+matched_list = [f for f in fcn_list if matcher(f,fcn_name)]
+overloaded = len(matched_list) > 1
+overloaded_str = ''
+index_str = ''
+if overloaded:
+ index_into_list = matched_list.index(fcn)
+ index_str = ','+str(index_into_list)
+ overloaded_str = '({} ({}::*)({}))'.format(fcn['return_type'],'',', '.join([f['dtype'] for f in fcn_args]))
+%>\
+% if fcn['name'] != filter_val:
+ ${modvar}.def("${fcn['name']}",${overloaded_str}&${namespace_name}::${fcn['name']},
+% for arg in fcn_args:
+ py::arg("${arg['name']}")${" = " + arg['default'] if arg['default'] else ''},
+% endfor ## args
+ D(${doc_prefix}${fcn['name']}${index_str})
+ );
+% endif ## Not a filtered function name
+</%def>
+
+<%def name='render_namespace(namespace, modname, modvar)'>
+<%
+ classes=namespace['classes'] if 'classes' in namespace else []
+ free_functions=namespace['free_functions'] if 'free_functions' in namespace else []
+ free_enums = namespace['enums'] if 'enums' in namespace else []
+ subnamespaces = namespace['namespaces'] if 'namespaces' in namespace else []
+ doc_prefix = '' if len(modname) == 1 else ','.join(modname[1:])+','
+%>\
+% for cls in classes:
+% if classes:
+ using ${cls['name']} = ${namespace['name']}::${cls['name']};
+% endif ##classes
+% endfor ##classes
+% for cls in classes:
+
+<%
+member_functions = cls['member_functions'] if 'member_functions' in cls else []
+constructors = cls['constructors'] if 'constructors' in cls else []
+class_enums = cls['enums'] if 'enums' in cls else []
+class_variables = cls['variables'] if 'variables' in cls else []
+try:
+ def find_make_function(member_fcns):
+ for mf in member_fcns:
+ if mf['name'] == 'make':
+ return mf
+ return None
+
+ make_function = find_make_function(member_functions)
+except:
+ make_function = None
+
+isablock = False
+if 'bases' in cls:
+ base_str = '::'.join(list(filter(lambda x: x != '::',cls['bases'])))
+ bases_with_block = [s for s in cls['bases'] if 'block' in s]
+ if bases_with_block:
+ isablock = True
+ # The goal is to make gr::sync_block have the entire chain back to basic_block
+ # if base_str == gr::sync_block, base_str == gr::sync_block,gr::block,gr::basic_block
+ if (base_str.endswith('gr::sync_block') or
+ base_str.endswith('gr::sync_interpolator') or
+ base_str.endswith('gr::sync_decimator') or
+ base_str.endswith('gr::tagged_stream_block')):
+ base_str += ", gr::block"
+ if base_str.endswith('gr::block'):
+ base_str += ", gr::basic_block"
+%>
+ py::class_<${cls['name']}\
+% if 'bases' in cls:
+, ${base_str},
+% else:
+,
+% endif\
+
+ std::shared_ptr<${cls['name']}>>(${modvar}, "${cls['name']}", D(${doc_prefix}${cls['name']}))
+
+% if make_function: ## override constructors with make function
+<%
+fcn = make_function
+fcn_args = fcn['arguments']
+%>\
+ .def(py::init(&${cls['name']}::${make_function['name']}),
+% for arg in fcn_args:
+ py::arg("${arg['name']}")${" = " + arg['default'] if arg['default'] else ''},
+% endfor
+ D(${doc_prefix}${cls['name']},${make_function['name']})
+ )
+
+% else:
+% for fcn in constructors:
+<%
+fcn_args = fcn['arguments']
+%>\
+\
+% if len(fcn_args) == 0:
+ .def(py::init<>(),D(${doc_prefix}${cls['name']},${cls['name']},${loop.index}))
+%else:
+ .def(py::init<\
+% for arg in fcn_args:
+${arg['dtype']}${'>(),' if loop.index == len(fcn['arguments'])-1 else ',' }\
+% endfor ## args
+\
+% for arg in fcn_args:
+ py::arg("${arg['name']}")${" = " + arg['default'] if arg['default'] else ''},
+% endfor
+ D(${doc_prefix}${cls['name']},${cls['name']},${loop.index})
+ )
+% endif
+% endfor ## constructors
+% endif ## make
+
+% for fcn in member_functions:
+${render_function(fcn=fcn,fcn_list=member_functions,cls_name=cls['name'],filter_val='make',doc_prefix=doc_prefix)}
+% endfor ## member_functions
+ ;
+% endfor ## classes
+
+% if free_enums:
+% for en in free_enums:
+<%
+values = en['values']
+%>\
+ py::enum_<${namespace['name']}::${en['name']}>(${modvar},"${en["name"]}")
+% for val in values:
+ .value("${val[0]}", ${namespace['name']}::${val[0]}) // ${val[1]}
+% endfor
+ .export_values()
+ ;
+% endfor
+% endif
+
+% if free_functions:
+% for fcn in free_functions:
+${render_free_function(fcn=fcn,fcn_list=free_functions,namespace_name=namespace['name'],filter_val="",modvar=modvar,doc_prefix=doc_prefix)}
+% endfor ## free_functions
+% endif ## free_functions
+\
+% for sns in subnamespaces:
+<%
+ submod_name = sns['name'].split('::')[-1]
+ next_modvar = modvar + '_' + submod_name
+%>
+ py::module ${next_modvar} = ${modvar}.def_submodule("${submod_name}");
+${render_namespace(namespace=sns,modname=modname+[submod_name],modvar=next_modvar)}
+% endfor
+
+</%def> \ No newline at end of file