在gfortran和g77编译的代码之间写入/读取控制台时的差异

时间:2013-11-20 16:27:08

标签: fortran stdout stdin gfortran g77

这个将需要一些解释。请耐心等待。

我有什么

我拥有一些Fortran源代码和一些从该代码编译的二进制文件。我没有进行编译,但是有一个构建脚本,建议G77用来做它。

除了Fortran之外,还有一些Java代码为用户提供围绕二进制文件的GUI“包装器”。它通过输入/输出/错误管道在自身和二进制文件之间传递信息。 Java代码非常混乱,这种做法增加了许多样板和冗余,但是它完成了工作并且我知道它有效。

我需要什么

不幸的是,我想做一些改变:

  1. 我想为二进制文件创建一个新的Python包装器(或者更确切地说,扩展现有的Python程序以成为新的包装器)。

  2. 我希望能够将Fortran代码编译为现有程序构建过程的一部分。我想使用gfortran,因为MinGW在构建中的其他地方使用,因此它将随时可用。

  3. 问题

    当我自己使用gfortran编译Fortran代码时,我无法将生成的二进制文件与当前的Java包装器或新的Python包装器“对话”。

    以下是我在Fortran代码中尝试打印到控制台的各种方法:

    subroutine printA(message)
      write(6,*) message
    end
    
    subroutine printB(message)
      write(*,*) message
    end
    
    subroutine printC(message)
      use iso_fortran_env
      write(output_unit,*) message
    end
    

    还有read个命令,但代码甚至没有更改执行该部分,所以我还没有担心它。

    额外信息

    • 我必须使用-ffixed-line-length-132标志调用gfortran以便代码编译,但除此之外我不使用任何其他内容。我已经尝试使用-ff2c标志,模糊地希望它能有所作为。它没有。

    • 这个stackoverflow post提供了丰富的信息,但没有提供任何有效的信息。

    • relavant manual page表示printA应该可以正常工作。

    • 我正在使用Windows,但需要将其作为多平台。

    • 如果您遇到了Juse,Java代码使用Runtime.getRuntime().exec("prog.exe")来调用二进制文件,然后使用生成的Process对象的各种“流”方法来与它们进行通信。 Python代码使用Popen模块的subprocess对象提供的等价物。

    • 我还应该说,我知道有其他选择。重写Python中的代码(或其他类似C ++的代码),或进行修改以便可以通过F2Py调用已被排除为选项。使用g77也是不行的;我们有足够的依赖关系。我希望能够使用gfortran正确地向控制台写入/读取,或者知道这是不可能的。

1 个答案:

答案 0 :(得分:1)

很难说没有看到Fortran和Python代码中的更多细节。以下代码对我有用(至少在Linux下):

Fortran程序逐行重复输入行,前缀为行号:

program test_communication
  use iso_fortran_env, stdout => output_unit, stdin => input_unit
  implicit none

  character(100) :: buffer
  integer :: ii

  ii = 1
  do while (.true.)
    read(stdin, *) buffer
    write(stdout, "(I0,A,A)") ii, "|", trim(buffer)
    flush(stdout)
    ii = ii + 1
  end do

end program test_communication

Python程序调用Fortran二进制文件。您可以使用控制台中的任意字符串来提供它。

import subprocess as sub

print "Starting child"
proc = sub.Popen("./a.out", stdin=sub.PIPE, stdout=sub.PIPE)
while True:
    send = raw_input("Enter a string: ")
    if not send:
        print "Exiting loop"
        break
    proc.stdin.write(send)
    proc.stdin.write("\n")
    proc.stdin.flush()
    print "Sent:", send
    recv = proc.stdout.readline()
    print "Received:", recv.rstrip()
print "Killing child"
proc.kill()