Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow allocatable function outputs and/or intent(out) #227

Closed
krystophny opened this issue Nov 15, 2024 · 1 comment
Closed

Allow allocatable function outputs and/or intent(out) #227

krystophny opened this issue Nov 15, 2024 · 1 comment

Comments

@krystophny
Copy link
Contributor

krystophny commented Nov 15, 2024

Currently, allocatable and pointer output arguments are not wrapped due to memory safety reasons. This would be required in particular for factory methods in the context of abstract base classes #41.

@jameskermode do you have an idea how much effort implementation of allocatable output arguments would mean?

Probably not too bad. The reason it's not supported is because of the risk of memory leaks when memory is allocated in Fortran but would need to be freed from Python. One solution would be not to return the allocatable output argument directly, but instead wrap it in a Python class with a destructor that frees the Fortran-allocated memory when the Python object goes out of scope.

Originally posted by @jameskermode in #41 (comment)

@krystophny
Copy link
Contributor Author

krystophny commented Nov 15, 2024

Testing now in https://github.com/itpplasma/f90wrap/tree/issue227_allocatable .

The test function is

function alloc_output_func(val) result(out)
    real, intent(in) :: val
    type(alloc_output_type), allocatable :: out
    allocate(out)
    out%a = val
end function alloc_output_func

The generated wrapper is

subroutine f90wrap_alloc_output__alloc_output_func(ret_out, val)
   ...
    allocate(ret_out_ptr%p)
    ret_out_ptr%p = alloc_output_func(val=val)
    ret_out = transfer(ret_out_ptr, ret_out)
end subroutine f90wrap_alloc_output__alloc_output_func

The type finaliser is

subroutine f90wrap_alloc_output__alloc_output_type_finalise(this)
   ...
    this_ptr = transfer(this, this_ptr)
    deallocate(this_ptr%p)
end subroutine f90wrap_alloc_output__alloc_output_type_finalise

which is correctly used by the Python wrapper

    def __del__(self):
        """
        Destructor for class Alloc_Output_Type
        ...
        """
        if self._alloc:
            _itest.f90wrap_alloc_output__alloc_output_type_finalise(this=self._handle)

So in the case of a function returning an allocatable derived type, the deallocation works out of the box. The extra allocate inside the wrapper is not necessary, but also not a problem, since standard Fortran should de-/reallocate on assignment, and no memory leak is generated. I check now the consequences for arrays too.

@jameskermode would that mean that one could allow allocatable derived types as function results right away and remove the extra allocate in a future feature within code generation?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant