Question

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?

Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top