Различия при записи / чтении из консоли между кодом, скомпилированным gfortran и g77

Это займет немного объяснений. Пожалуйста, потерпите меня.

Что я имею

У меня есть некоторый исходный код на Фортране и несколько двоичных файлов, скомпилированных из этого кода. Я не делал компиляцию, но есть сценарий сборки, который предполагает, что G77 был использован для этого.

Помимо фортрановского контента, есть также некоторый Java-код, который предоставляет пользователям GUI-оболочку для двоичных файлов. Он передает информацию между собой и двоичными файлами через их каналы ввода / вывода / ошибки. Java-код очень грязный, и такой способ работы добавляет много шаблонного и избыточного, но он делает свою работу, и я знаю, что это работает.

Что мне нужно

К сожалению, я хотел бы внести некоторые изменения:

  1. Я хочу создать новую оболочку Python для двоичных файлов (или, точнее, расширить существующую программу Python, чтобы она стала новой оболочкой).

  2. Я хочу иметь возможность компилировать код на Фортране как часть процесса сборки этой существующей программы. Я хотел бы использовать gfortran для этого, так как MinGW используется в другом месте сборки, и поэтому он будет легко доступен.

Эта проблема

Когда я сам компилирую код Fortran, используя gfortran, я не могу заставить полученные двоичные файлы "общаться" ни с текущей оболочкой Java, ни с моей новой оболочкой Python.

Вот различные способы печати на консоли, которые я пробовал в коде Фортрана:

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 команды, но в коде даже нет изменений для выполнения этой части, поэтому я пока не беспокоюсь об этом.

Дополнительная информация

  • Я должен позвонить Gfortran с -ffixed-line-length-132 флаг, чтобы код компилировался, но кроме этого я больше ничего не использую. Я пытался использовать -ff2c флаг в смутной надежде, что это будет иметь значение. Это не так.

  • Эта статья о стековом потоке является информативной, но не предлагает мне ничего, что работает.

  • Соответствующая страница руководства предполагает, что printA должен работать просто отлично.

  • Я работаю над Windows, но это нужно для мультиплатформенности.

  • Juse, в случае, если вы прошли проверку, код Java использует Runtime.getRuntime().exec("prog.exe") вызвать двоичные файлы, а затем различные "потоковые" методы результирующего Process объект для общения с ними. Код Python использует эквиваленты этого, предоставленные Popen объект subprocess модуль.

  • Я должен также сказать, что я знаю, что есть альтернативы. Переписывание кода на Python (или что-то еще, например, C++) или внесение изменений, чтобы он мог вызываться через F2Py, были исключены в качестве опций. Использование g77 также не допускается; у нас достаточно зависимостей как есть. Я хотел бы иметь возможность писать / читать с консоли должным образом с помощью gfortran или знать, что это просто невозможно.

1 ответ

Решение

Трудно сказать, не видя больше деталей из ваших кодов Фортрана и 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, вызывающая бинарный файл Фортрана. Вы можете кормить его произвольными строками из консоли.

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()
Другие вопросы по тегам