If fn can be interpreted and handled as a native function: i.e.
    fn is one of the extensions, or fn is a simple lambda closure using one of
    the extensions.

       fn = tc.extensions.add
       fn = lambda x: tc.extensions.add(5)

    Then, this returns a closure object, which describes the function call
    which can then be passed to C++.

    Returns a _Closure object on success, raises an exception on failure.

def _build_native_function_call(fn):
    """
    If fn can be interpreted and handled as a native function: i.e.
    fn is one of the extensions, or fn is a simple lambda closure using one of
    the extensions.

       fn = tc.extensions.add
       fn = lambda x: tc.extensions.add(5)

    Then, this returns a closure object, which describes the function call
    which can then be passed to C++.

    Returns a _Closure object on success, raises an exception on failure.

    """
    # See if fn is the native function itself
    native_function_name = _get_toolkit_function_name_from_function(fn)
    if native_function_name != "":
        # yup!
        # generate an "identity" argument list
        argnames = _get_argument_list_from_toolkit_function_name(native_function_name)
        arglist = [[0, i] for i in range(len(argnames))]
        return _Closure(native_function_name, arglist)

    # ok. its not a native function
    from .util.lambda_closure_capture import translate
    from .util.lambda_closure_capture import Parameter

    # Lets see if it is a simple lambda
    capture = translate(fn)
    # ok. build up the closure arguments
    # Try to pick up the lambda
    function = _descend_namespace(capture.caller_globals, capture.closure_fn_name)
    native_function_name = _get_toolkit_function_name_from_function(function)
    if native_function_name == "":
        raise RuntimeError("Lambda does not contain a native function")

    argnames = _get_argument_list_from_toolkit_function_name(native_function_name)

    # ok. build up the argument list. this is mildly annoying due to the mix of
    # positional and named arguments
    # make an argument list with a placeholder for everything first
    arglist = [[-1, i] for i in argnames]
    # loop through the positional arguments
    for i in range(len(capture.positional_args)):
        arg = capture.positional_args[i]
        if type(arg) is Parameter:
            # This is a lambda argument
            # arg.name is the actual string of the argument
            # here we need the index
            arglist[i] = [0, capture.input_arg_names.index(arg.name)]
        else:
            # this is a captured value
            arglist[i] = [1, arg]

    # now. the named arguments are somewhat annoying
    for i in capture.named_args:
        arg = capture.named_args[i]
        if type(arg) is Parameter:
            # This is a lambda argument
            # arg.name is the actual string of the argument
            # here we need the index
            arglist[argnames.index(i)] = [0, capture.input_arg_names.index(arg.name)]
        else:
            # this is a captured value
            arglist[argnames.index(i)] = [1, arg]

    # done. Make sure all arguments are filled
    for i in arglist:
        if i[0] == -1:
            raise RuntimeError("Incomplete function specification")

    # attempt to recursively break down any other functions
    import inspect
    for i in range(len(arglist)):
        if arglist[i][0] == 1 and  inspect.isfunction(arglist[i][1]):
            try:
                arglist[i][1] = _build_native_function_call(arglist[i][1])
            except:
                pass
    return _Closure(native_function_name, arglist)