Я связываю код Fortran с Cll DLL, и я хотел бы, чтобы массив Fortran был совместим с C. У меня есть следующая подпрограмма для связывания массива Fortran с 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
Однако, что мне не нравится в текущем коде, так это то, что я постоянно выделяю память и вынужден распаковывать массив при вводе C dll (отчасти это вызвано моим нежеланием использовать SAVE
атрибут на In_X(:)
). Я бы очень хотел заявить In_X
однажды, внутри производного типа Фортрана. Это приводит к мотивации для этого поста. В этом производном типе:
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
Я получаю ошибку:
REAL(KIND=C_DOUBLE) , ALLOCATABLE , TARGET :: In_X(:)
1
Error: Attribute at (1) is not allowed in a TYPE definition
Есть ли способ устранить эту ошибку?
Я сталкивался с этой проблемой раньше, и решение, которое работало для меня, состояло в том, чтобы объявить компонент как POINTER
вместо ALLOCATABLE, TARGET
, Я не уверен, что стандарт Fortran не поддерживает его, или эта функция просто не реализована компиляторами. Я использовал ifort v12.0.2.137
,
Будет ли это приемлемым решением для вас? Затем вы сможете использовать его в качестве цели указателя.
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
Затем вы можете связать In_X
указатель с целевыми данными:
In_X(1:Input%C_obj%Xlen) => Input%X(1:Input%C_obj%Xlen)
Обратите внимание, что Input%X
нужно будет иметь TARGET
атрибут также.
Других решений пока нет …