最近在debug的时候看到CMAQ ioapi的code, envgets.c中和ENVSTR函数和m3utilio.F中的接口参数不一致, 但是可以正常跑, 之前没注意过, 我大为震惊, code如下:
// ioapi/envgets.c
void ENVSTR( const char * lname,
const char * description,
const char * defaultval,
char * eqname,
FINT * status,
FSTR_L namlen,
FSTR_L deslen,
FSTR_L deflen,
FSTR_L eqlen )
{
... ...
}
! ioapi/m3utilio.F
INTERFACE
SUBROUTINE ENVSTR( LNAME, DESC, DEFAULT, EQNAME, STAT )
CHARACTER*(*), INTENT(IN ) :: LNAME
CHARACTER*(*), INTENT(IN ) :: DESC
CHARACTER*(*), INTENT(IN ) :: DEFAULT
CHARACTER*(*), INTENT( OUT) :: EQNAME
INTEGER , INTENT( OUT) :: STAT
END SUBROUTINE ENVSTR
END INTERFACE
然后自己做了个简单的测试
// echo.c
#include<stdio.h>
void echo_(const char *s1, const char *s2)
{
printf("%s\n", s1);
printf("%s\n", s2);
}
void echo2_(char *s1, char *s2, int l1, int l2)
{
printf("%s\n", s1);
printf("%s\n", s2);
printf("%d\n", l1);
printf("%d\n", l2);
}
! main.f90
PROGRAM main
implicit none
INTEGER :: a, b, c, e
CHARACTER(14) :: s1, s2
INTERFACE
SUBROUTINE ECHO(s1, s2)
CHARACTER(*) :: s1, s2
END SUBROUTINE
SUBROUTINE ECHO2(s1, s2)
CHARACTER(*) :: s1, s2
END SUBROUTINE
END INTERFACE
s1 = "1234567890123" ! // achar(0)
s2 = "world"
call ECHO(s1, s2)
call ECHO2(s1, s2)
END PROGRAM main
# makefile
test :
icc -c -o echo.o echo.c
ifort -c -o main.o main.f90
ifort main.o echo.o -o main.exe
执行得:
1234567890123 world
world
14
14
可以发现几个问题:
- FORTRAN和C的参数个数确实不需要匹配也ok
- 字符串在从FORTRAN到C的时候是会出问题的(第一行直接打印s1有明显错误)
- 会在FORTRAN的参数后面加上字符串的长度(我推测这个机制和上一点是有关系的)
然后经过查证, 在官方的doc里确实也提到了这个feature, 之前没注意到这么细
Oracle Chapter 11 C-FortranInterface
另外这个只是针对字符串的, 试了下对数组是不会带长度的, 但是参数不需要匹配就能跑是都行的, 只是其他情况大概会报错