{% set four_spaces="    " %}
{% set return_value_name = return_value.definition.name %}
{% set return_value_is_pointer=return_value.definition.as_fortran_data_type().is_pointer %}
{####}
subroutine {{ fortran_wrapper_module_callable }}( &
    instance_index, &
{% for param in input_params %}
    {{ param }}, &
{% endfor %}
    {{ return_value_name }}{{ instance_index_suffix }} &
    )

{# Type declarations #}
    {# TODO: use shared here rather than hard-coded instance_index #}
    integer, intent(in) :: instance_index
{%
    for parameter_name, parameter_passing_type, parameter
    in receiving_from_python_steps.fortran_wrapper_callable_parameters
%}

    {{ parameter_passing_type }}, intent(in) :: {{ parameter_name }}
    ! Passing of {{ parameter.definition.name }}
{% endfor %}

{# Always return the instance index, an integer, Python handles joining things back up #}
    integer, intent(out) :: {{ return_value_name }}{{ instance_index_suffix }}
    ! Returning of {{ return_value_name }}

    type({{ class_being_wrapped }}), pointer :: instance
    {{ wrapper_module_type_attribute_declaration }} :: {{ return_value_name }}
{%
    for argument_name, type_declaration
    in receiving_from_python_steps.not_directly_passed_fortran_module_callable_args_type_declarations
%}
    {{ type_declaration }} :: {{ argument_name }}
{% endfor %}

{# Manager calls #}
{# TODO: use shared for manager_get_instance here rather than hard-coding #}
    call manager_get_instance(instance_index, instance)

{% if receiving_from_python_steps.postprocessing_fortran_calls %}
    {{ receiving_from_python_steps.postprocessing_fortran_calls | indent_based_on_first_line(four_spaces) }}

{% endif %}
{####}
    ! Get a new instance to use for returning.
    ! We can't return the value
    ! because then Python has no idea what to refer to
    ! if the user asks to see the state of the returned valued
    ! (because the returned value is not managed by our manager).
{#
    We could probably hold a mapping of derived_type_via_allocatable indexes
    to derived_type indexes so we didn't create a new object everytime,
    but that is probably a lot of mucking around for little gain.
    The current solution will chew through available instances though if you request the attribute many times
    because there is no clean up of the created objects
    (or it will leak memory, once we stop pre-allocating all our derived type instances).
#}
    {{ return_value_name }}{{ instance_index_suffix }} = {{ return_value_manager_get_free_instance_number }}()
    call {{ return_value_manager_get_instance }}({{ return_value_name }}{{ instance_index_suffix }}, {{ return_value_name }})

{# Call the method #}
{% set fprettify_indent= " " * return_value_name | length + "   " %}
    {{ return_value_name }} = instance % {{ method_name }}( &
{% for arg in receiving_from_python_steps.fortran_module_callable_args_names %}
    {{ fprettify_indent }}{{ arg }}={{ arg }}{% if not loop.last %},{% endif %} &
{% endfor %}
    {{ fprettify_indent }})
    ! Ensure that the returned value will point to the right spot in our managed instances
    {{ return_value_name }} % instance_index = {{ return_value_name }}{{ instance_index_suffix }}

end subroutine {{ fortran_wrapper_module_callable }}
