Passing pointer array to dummy parameter declared as allocatable array

Passing pointer array to dummy parameter declared as allocatable array


I am modifying a Fortran code which has some arrays declared as allocatable. The changes I am doing require changing the allocatable arrays to pointer arrays as they are being passed to C++ routines and back. The problem is that, there are subroutines on the Fortran side that still expect these arrays to be passed as allocatable, and I need to make sure that my changes don't affect the declaration of these subroutines as the code has multiple developers.

I was trying a small test example on passing an array that has been declared as a pointer, to a routine that expects an allocatable array. The solution I found is not very great, and requires using another allocatable array. I give the snippet below.

program test
implicit none
integer, parameter :: VAL = 2
integer, pointer, dimension(:,:,:) :: a
integer, allocatable, dimension(:,:,:) :: b
allocate(a(VAL,VAL,VAL), stat=ierr)
allocate(b(VAL,VAL,VAL), stat=ierr)
!set values in a
b = a
call checkval(b)
subroutine checkval(arr)
implicit none
integer, dimension(:,:,:), allocatable :: arr
arr(:, :, :) = -1
end subroutine checkval
end program array

This seems to be a very trivial way to solve this, and will make use of more memory due to the allocatable array b, when VAL is large. Is it possible to do this in a smarter way.



7 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

Is the C++ code accessing/modifying the passed array, or are you simply passing the address of the array between languages as an opaque token?  If the latter, then you may be able to wrap the allocatable array in a derived type and preserve its allocatable nature.

If a procedure has an allocatable dummy argument it is usually because it needs to query aspects relating to the allocation (is the array allocated, what are the bounds of the allocated thing) or is going to modify the allocation in some way.  You may need to take this into account in your wrapper code.

As IanH hinted, if the C/C++ code is not going to allocate/deallocate/reallocate the array(s) passed to it, there is no need to mark the formal argument as ALLOCATABLE. In your Fortran example above, you may remove ALLOCATABLE from Line-14.


Thanks for your help so far. Maybe I will elaborate the problem a bit.

Initially, the data was completely being stored in the Fortran side. Now, the data needs to be stored on the C++ side, and passed back to the Fortran side. The C++ side will modify the data since the data is being passed to a C++ mesh refinement library. On the Fortran side as well, the subroutines will modify the data. Using a pointer allowed the data to be up to date on both sides. I am not sure if using ALLOCATABLE array on the Fortran side can point to data created on the C++ side and be up to date as well unless I copy it.


No - do not use ALLOCATABLE for this purpose. There is a "Technicsl Specification" for improved C interoperability in the Fortran standard, which will be included in "Fortran 2015", that provides ways for C code to manipulate Fortran allocatable variables. But it isn't here yet. You should pass variables of type C_PTR (from module ISO_C_BINDING) and use the C_F_POINTER subroutine to "cast" them into Fortran pointers so that Fortran code can use the data.

Retired 12/31/2016

Hi Steve,

Thanks for your reply. Yes, I will be declaring the 3D arrays as POINTER on the Fortran side.

I'm not exactly sure what you're doing, so let me make some general comments.

You talk about 3D arrays.  C doesn't have such a thing - in C, what looks like a multidimensional array is actually an array of pointers to arrays, something with no exact analog in Fortran.  I assume you know this and know how to properly index such data in C - and also that you know about 0-based vs. 1-based indexing, and row-major vs. column-major order.

A Fortran POINTER is not something C code can use directly. If you want to allocate data in C and have it used by Fortran, have the C code pass the data pointer and declare it as TYPE(C_PTR) on the Fortran side.  Then declare a Fortran POINTER array with deferred shape (:.:.:) and use the C_F_POINTER intrinsic subroutine to fill in the POINTER with the appropriate information.  You supply the bounds as an argument to C_F_POINTER.

Alternatively, you can pass the C pointer by value and declare the Fortran dummy argument as an adjustable array (with bounds taken from other arguments), or constant bounds, or with the last bound *.

Retired 12/31/2016

Leave a Comment

Please sign in to add a comment. Not a member? Join today