(headerfile, ch, comments, inst, remaps)
return plugin, bound, unbound
Take a header file (headerfile) and a parse tree (ch)
    and build the pybind11 plugin

    headerfile: somefile.h

    ch: parse tree from CppHeaderParser

    comments: a dictionary of comments

    inst: files to instantiate

    remaps: list of remaps
Take a header file (headerfile) and a parse tree (ch)
    and build the pybind11 plugin
Take a header file ( headerfile ) and a parse tree ( ch ) and build the pybind11 plugin
def build_plugin(headerfile, ch, comments, inst, remaps):
    """
    Take a header file (headerfile) and a parse tree (ch)
    and build the pybind11 plugin

    headerfile: somefile.h

    ch: parse tree from CppHeaderParser

    comments: a dictionary of comments

    inst: files to instantiate

    remaps: list of remaps
    """
    headerfilename = os.path.splitext(headerfile)[0]

    indent = '    '
    plugin = ''

    # plugin += '#define NC py::arg().noconvert()\n'
    # plugin += '#define YC py::arg()\n'
    plugin += f'PYBIND11_MODULE({headerfilename}, m) {{\n'
    plugin += indent + 'm.doc() = R"pbdoc(\n'
    plugin += indent + f'Pybind11 bindings for {headerfile}\n\n'
    plugin += indent + 'Methods\n'
    plugin += indent + '-------\n'
    for f in ch.functions:
        templated = bool(f['template'])
        if not templated:
            plugin += indent + f['name'] + '\n'
        if templated:
            for func in inst:
                if f['name'] in func['functions']:
                    plugin += indent + f['name'] + '\n'
    plugin += indent + ')pbdoc";\n\n'

    plugin += indent + 'py::options options;\n'
    plugin += indent + 'options.disable_function_signatures();\n\n'

    unbound = []
    bound = []
    for f in ch.functions:
        # for each function:
        #   1 determine if the function is templated
        #   2 if templated:
        #       - find the entry in the instantiation list
        #   3 note any array parameters to the function
        #   4 if templated:
        #       - for each type, instantiate and bind
        #   5 if not templated:
        #       - bind

        # 1
        templated = bool(f['template'])

        # 2
        found = False
        if templated:
            for func in inst:
                if f['name'] in func['functions']:
                    found = True
                    types = func['types']

            if not found:
                # print('Could not find an instantiation for {}'.format(f['name']))
                unbound.append(f['name'])
                continue
            else:
                bound.append(f['name'])
        else:
            unbound.append(f['name'])
            types = [None]
            continue

        # 3
        # find all parameter names and mark if array
        argnames = []
        for p in f['parameters']:

            array = False
            if p['pointer'] or p['array']:
                array = True

            # skip "_size" parameters
            if '_size' in p['name']:
                continue
            else:
                argnames.append((p['name'], array))

        ntypes = len(types)
        for i, t in enumerate(types):

            # add the function call with each template
            instname = f['name']

            # check the remaps
            for remap in remaps:
                if f['name'] in remap:
                    instname = remap[f['name']]

            if t is not None:
                # templated function
                typestr = '<' + ', '.join(t) + '>'
            else:
                # not a templated function
                typestr = ''

            plugin += indent + \
                'm.def("{}", &_{}{}'.format(instname, f['name'], typestr)

            # name the arguments
            pyargnames = []
            for p, array in argnames:
                convert = ''
                if array:
                    convert = '.noconvert()'
                pyargnames.append(f'py::arg("{p}"){convert}')

            argstring = indent + indent + ', '.join(pyargnames)
            if len(pyargnames) > 0:
                argstring = ',\n' + argstring
            plugin += argstring

            # add the docstring to the last
            if i == ntypes - 1:
                plugin += ',\nR"pbdoc(\n{})pbdoc");\n'.format(
                    comments[f['name']])
            else:
                plugin += ');\n'
        plugin += '\n'

    plugin += '}\n'

    return plugin, bound, unbound
def build_plugin ( headerfile , ch , comments , inst , remaps ) : headerfilename = os . path . splitext ( headerfile ) [ 0 ] indent = '    ' plugin = '' # plugin += '#define NC py::arg().noconvert()\n' # plugin += '#define YC py::arg()\n' plugin += f'PYBIND11_MODULE({headerfilename}, m) {{\n' plugin += indent + 'm.doc() = R"pbdoc(\n' plugin += indent + f'Pybind11 bindings for {headerfile}\n\n' plugin += indent + 'Methods\n' plugin += indent + '-------\n' for f in ch . functions : templated = bool ( f [ 'template' ] ) if not templated : plugin += indent + f [ 'name' ] + '\n' if templated : for func in inst : if f [ 'name' ] in func [ 'functions' ] : plugin += indent + f [ 'name' ] + '\n' plugin += indent + ')pbdoc";\n\n' plugin += indent + 'py::options options;\n' plugin += indent + 'options.disable_function_signatures();\n\n' unbound = [ ] bound = [ ] for f in ch . functions : # for each function: #   1 determine if the function is templated #   2 if templated: #       - find the entry in the instantiation list #   3 note any array parameters to the function #   4 if templated: #       - for each type, instantiate and bind #   5 if not templated: #       - bind # 1 templated = bool ( f [ 'template' ] ) # 2 found = False if templated : for func in inst : if f [ 'name' ] in func [ 'functions' ] : found = True types = func [ 'types' ] if not found : # print('Could not find an instantiation for {}'.format(f['name'])) unbound . append ( f [ 'name' ] ) continue else : bound . append ( f [ 'name' ] ) else : unbound . append ( f [ 'name' ] ) types = [ None ] continue # 3 # find all parameter names and mark if array argnames = [ ] for p in f [ 'parameters' ] : array = False if p [ 'pointer' ] or p [ 'array' ] : array = True # skip "_size" parameters if '_size' in p [ 'name' ] : continue else : argnames . append ( ( p [ 'name' ] , array ) ) ntypes = len ( types ) for i , t in enumerate ( types ) : # add the function call with each template instname = f [ 'name' ] # check the remaps for remap in remaps : if f [ 'name' ] in remap : instname = remap [ f [ 'name' ] ] if t is not None : # templated function typestr = '<' + ', ' . join ( t ) + '>' else : # not a templated function typestr = '' plugin += indent + 'm.def("{}", &_{}{}' . format ( instname , f [ 'name' ] , typestr ) # name the arguments pyargnames = [ ] for p , array in argnames : convert = '' if array : convert = '.noconvert()' pyargnames . append ( f'py::arg("{p}"){convert}' ) argstring = indent + indent + ', ' . join ( pyargnames ) if len ( pyargnames ) > 0 : argstring = ',\n' + argstring plugin += argstring # add the docstring to the last if i == ntypes - 1 : plugin += ',\nR"pbdoc(\n{})pbdoc");\n' . format ( comments [ f [ 'name' ] ] ) else : plugin += ');\n' plugin += '\n' plugin += '}\n' return plugin , bound , unbound