Question

This one's going to take a bit of explaining. Please bear with me.

What I Have

I have in my possession some Fortran source code and some binaries that have been compiled from that code. I did not do the compilation, but there is a build script that suggests G77 was used to do it.

As well as the Fortran stuff, there is also some Java code that provides users with a GUI "wrapper" around the binaries. It passes information between itself and the binaries via their input/output/error pipes. The Java code is very messy, and this way of doing things adds a lot of boilerplate and redundancy, but it does the job and I know it works.

What I Need

Unfortunately, I'd like to make some changes:

  1. I want to create a new Python wrapper for the binaries (or, more precisely, extend an existing Python program to become the new wrapper).

  2. I want to be able to compile the Fortran code as part of this existing program's build process. I would like to use gfortran for this, since MinGW is used elsewhere in the build and so it will be readily available.

The Problem

When I compile the Fortran code myself using gfortran, I cannot get the resulting binaries to "talk" to either the current Java wrapper or my new Python wrapper.

Here are the various ways of printing to the console that I have tried in the Fortran code:

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

There are also read commands as well, but the code doesn't even get a change to execute that part so I'm not worrying about it yet.

Extra Info

  • I have to call gfortran with the -ffixed-line-length-132 flag so that the code compiles, but apart from that I don't use anything else. I have tried using the -ff2c flag in the vague hope that it will make a difference. It doesn't.

  • This stackoverflow post is informative, but doesn't offer me anything that works.

  • The relavant manual page suggests that printA should work just fine.

  • I'm working on Windows, but will need this to be multi-platform.

  • Juse in case you're intested, the Java code uses Runtime.getRuntime().exec("prog.exe") to call the binaries and then the various "stream" methods of the resulting Process object to communicate with them. The Python code uses equivalents of this provided by the Popen object of the subprocess module.

  • I should also say that I am aware there are alternatives. Rewriting the code in Python (or something else like C++), or making amendments so that is it can be called via F2Py have been ruled out as options. Using g77 is also a no-go; we have enough dependencies as it is. I'd like to be able to write to / read from the console properly with gfortran, or know that it's just not possible.

Was it helpful?

Solution

Hard to say without seeing more details from your Fortran and Python codes. The following pair of code works for me (at least under Linux):

Fortran program repeating its input line by line prefixed with line number:

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 program invoking the Fortran binary. You can feed it with arbitrary strings from the console.

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()
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top