I'm binding Fortran code with a C dll, and I would like to have a Fortran array inter-operable with C. I currently have the following subroutine to bind the Fortran array with a C double*:
SUBROUTINE Pack_Inputs( Input , In_X )
TYPE( InputType ) , INTENT(INOUT) :: Input
REAL(KIND=C_DOUBLE) , ALLOCATABLE , TARGET , INTENT(INOUT) :: In_X(:)
IF ( .NOT. ALLOCATED(In_X) ) ALLOCATE( In_X (Input%Xlen) )
DO i = 1,Input%C_obj%Xlen
In_X(i) = Input%X(i)
END DO
Input%C_obj%X = C_LOC(In_X)
END SUBROUTINE Pack_Inputs
However, what I don't like about the current code is that I am constantly allocating memory, and having to unpack the array when the C dll is entered (partly driven by my reluctance to use the SAVE
attribute on In_X(:)
). I would rather much declare In_X
once, inside a Fortran derived type. This leads to the motivation for this post. In this derived type:
USE , INSTRINSIC :: ISO_C_BINDING
TYPE , PUBLIC :: InputType
TYPE(InputType_C) :: C_obj
REAL(KIND=C_DOUBLE) , ALLOCATABLE , TARGET :: In_X(:)
REAL , DIMENSION(:) , ALLOCATABLE :: X
REAL , DIMENSION(:) , ALLOCATABLE :: Y
REAL , DIMENSION(:) , ALLOCATABLE :: Z
INTEGER , DIMENSION(:) , ALLOCATABLE :: index
INTEGER :: Xlen
INTEGER :: Ylen
INTEGER :: Zlen
INTEGER :: indexlen
END TYPE InputType
I get the error:
REAL(KIND=C_DOUBLE) , ALLOCATABLE , TARGET :: In_X(:)
1
Error: Attribute at (1) is not allowed in a TYPE definition
Is there a way to eliminate this error?
I have encountered this problem before, and the solution that worked for me was to to declare the component as POINTER
instead of ALLOCATABLE, TARGET
. I am not sure whether the Fortran standard does not support it, or this feature is just not implemented by the compilers. I was using ifort v12.0.2.137
.
Would this be an acceptable solution for you? You would then be able to use it as pointer target.
TYPE , PUBLIC :: InputType
TYPE(InputType_C) :: C_obj
REAL(KIND=C_DOUBLE),DIMENSION(:),POINTER :: In_X => NULL()
REAL , DIMENSION(:) , ALLOCATABLE :: X
REAL , DIMENSION(:) , ALLOCATABLE :: Y
REAL , DIMENSION(:) , ALLOCATABLE :: Z
INTEGER , DIMENSION(:) , ALLOCATABLE :: index
INTEGER :: Xlen
INTEGER :: Ylen
INTEGER :: Zlen
INTEGER :: indexlen
END TYPE InputType
Then, you can associate the In_X
pointer with target data:
In_X(1:Input%C_obj%Xlen) => Input%X(1:Input%C_obj%Xlen)
Note that Input%X
will need to have a TARGET
attribute as well.