gfortran指定-frecord-marker=8编译后,Python调用Fortran子程序报错
-frecord-marker=8未生效,导致Fortran二进制文件读取报错 我通过Python的ctypes调用Fortran子程序读取二进制文件,相关代码如下:
Fortran代码(reader.f95)
subroutine readdata() bind(c, name='readdata') use iso_c_binding ..... write(*,'(/,A)')'Reading marco file...' !OPEN LINK FILE IR4 = 12 OPEN(UNIT=IR4,FILE="FLTGEO.LIX",STATUS='OLD',FORM='UNFORMATTED',IOSTAT=IERR) IF (IERR/=0)STOP 'FAILED TO OPEN LINK FILE - CHECK!' READ(IR4) ROOL WRITE(*,*) "ROOL: ", ROOL .... CLOSE(IR4) end subroutine readdata
编译命令
gfortran -shared -frecord-marker=8 -o reader.so reader.f95
动态库生成正常,但Python调用时出现错误:
Reading marco file...
ROOL:
At line 18 of file reader.f95 (unit = 12, file = 'FLTGEO.LIX')
Fortran runtime error: I/O past end of record on unformatted file
错误显示程序似乎仍在使用默认的4字节记录标记,而非编译时指定的8字节。使用的gfortran版本为GNU Fortran (GCC) 13.2.1 20230801。
显式在OPEN语句中指定流模式读取:
放弃依赖编译选项控制记录标记,直接在OPEN语句中添加ACCESS='STREAM',让Fortran以字节流方式读取文件,跳过记录标记的处理。修改后的OPEN语句如下:OPEN(UNIT=IR4,FILE="FLTGEO.LIX",STATUS='OLD',FORM='UNFORMATTED',ACCESS='STREAM',IOSTAT=IERR)这种方式需要确保读取的变量字节数与文件中对应数据的字节数完全匹配,避免因数据长度不匹配导致的错误。
验证编译选项是否实际生效:
重新编译时添加-v参数查看详细编译过程,确认-frecord-marker=8选项被正确应用:gfortran -shared -frecord-marker=8 -o reader.so reader.f95 -v同时删除旧的
reader.so文件后再重新编译,避免缓存的旧库干扰。检查文件的实际记录标记格式:
使用hexdump -C FLTGEO.LIX查看文件开头的字节,确认记录标记的实际大小。如果文件是由其他编译器(如Intel Fortran)生成的,可能需要额外指定字节序选项,比如在OPEN语句中添加CONVERT='BIG_ENDIAN'或CONVERT='LITTLE_ENDIAN',匹配原文件的字节序。尝试直接指定记录长度:
如果知道文件中每条记录的实际字节长度,可以在OPEN语句中添加ACCESS='DIRECT'和RECL=记录长度参数,强制按指定长度读取记录:OPEN(UNIT=IR4,FILE="FLTGEO.LIX",STATUS='OLD',FORM='UNFORMATTED',ACCESS='DIRECT',RECL=XX,IOSTAT=IERR)其中
XX替换为实际的记录长度(注意gfortran中RECL的单位是字节,部分其他编译器可能是字长)。
内容的提问来源于stack exchange,提问作者Michael Leanza

