使用函数调用非法使用派生类型

时间:2011-10-24 17:06:03

标签: fortran fortran90

我有一个简单的函数,它根据时间字符串返回一个时间对象:

FUNCTION getTime(timeStr)RESULT(time)
IMPLICIT NONE
CHARACTER(LEN=19),INTENT(IN) :: timeStr
TYPE timeType
 INTEGER :: yyyy,mo,dd,hh,mm,ss
ENDTYPE timeType
TYPE(timeType) :: time
READ(UNIT=timeStr( 1: 4),'(I4)')time%yyyy
READ(UNIT=timeStr( 6: 7),'(I2)')time%mo
READ(UNIT=timeStr( 9:10),'(I2)')time%dd
READ(UNIT=timeStr(12:13),'(I2)')time%hh
READ(UNIT=timeStr(15:16),'(I2)')time%mm
READ(UNIT=timeStr(18:19),'(I2)')time%ss
ENDFUNCTION getTime

我从父例程中将其称为:

umwmTime1=getTime(umwmStartTimeStr)
umwmTime2=getTime(umwmStopTimeStr)

其中umwmTime 1和2声明为:

TYPE timeType
  INTEGER :: yyyy,mo,dd,hh,mm,ss
ENDTYPE timeType
TYPE(timeType) :: umwmTime1,umwmTime2

我得到的编译错误信息是:

PGF90-S-0099-Illegal use of derived type (ESMF_interface_UMWM.F90: 282)
PGF90-S-0099-Illegal use of derived type (ESMF_interface_UMWM.F90: 283)
  0 inform,   0 warnings,   2 severes, 0 fatal for umwm_component_run

第282和283行是父例程中的函数调用。

但是如果我使用子程序(而不是函数)将umwmTime1和umwmTime2作为INTENT(OUT)参数,我没有遇到任何问题。我在做什么错误的功能?

2 个答案:

答案 0 :(得分:6)

问题是编译器不知道您在主程序中定义的时间类型与您在函数中定义的时间类型相同。你应该定义一个地方,最好是在一个模块中,然后让它在任何地方定义类型。

例如,在一个简单的单文件程序中,您提供的代码在gfortran中对我不起作用,但这样做:

MODULE timeTypeDef
TYPE timeType
    INTEGER :: yyyy,mo,dd,hh,mm,ss
ENDTYPE timeType
END MODULE timeTypeDef

PROGRAM foo
USE timeTypeDef
IMPLICIT NONE

TYPE(timeType) :: umwmTime1, umwmTime2

umwmTime1=getTime('2010-10-10-14:39:03')
umwmTime2=getTime('2011-11-11-09:17:53')

contains

FUNCTION getTime(timeStr)RESULT(time)
    USE timeTypeDef
    IMPLICIT NONE
    CHARACTER(LEN=19),INTENT(IN) :: timeStr
    TYPE(timeType) :: time

    READ(UNIT=timeStr( 1: 4),FMT='(I4)')time%yyyy
    READ(UNIT=timeStr( 6: 7),FMT='(I2)')time%mo
    READ(UNIT=timeStr( 9:10),FMT='(I2)')time%dd
    READ(UNIT=timeStr(12:13),FMT='(I2)')time%hh
    READ(UNIT=timeStr(15:16),FMT='(I2)')time%mm
    READ(UNIT=timeStr(18:19),FMT='(I2)')time%ss
ENDFUNCTION getTime

END PROGRAM foo

答案 1 :(得分:0)

在模块中放置函数“getTime”并在调用例程中使用该模块。

问题是调用例程不知道例程函数getTime返回TYPE(timeType)。默认情况下,getTime被视为实际标量值。因此,您需要一个可由USE语句轻松提供的显式接口。此接口也可以由INTERFACE块提供,但不建议这样做,因为容易出错。

我还想指出参数timeStr的声明“CHARACTER(len = 19)”非常危险。我建议改为:

FUNCTION getTime(timeStr)RESULT(time)
IMPLICIT NONE
CHARACTER(LEN=*),INTENT(IN) :: timeStr
...

实际上,使用少于19个字符的字符串参数调用该函数是错误的。