Как получить местоположение моего исполняемого файла с помощью Fortran?

У меня есть программа, написанная на Фортране 90/95; после вызова он всегда читает определенный файл данных. Для удобства пользователей я бы хотел, чтобы они просто поместили этот файл в тот же каталог, что и сам исполняемый файл, не заставляя их устанавливать какую-либо переменную среды /extension $PATH, и не заставляя их использовать для этой цели определенный каталог., Программа должна "просто" искать файл в каталоге, в котором он сам хранится, а не в каталоге, из которого он запущен. Однако до сих пор мне не удалось найти решение этой проблемы. Я пытался с помощью

getarg(0,path)

но это дало мне только строку, которую я использовал для вызова программы, а не ее абсолютный путь.

Если у вас есть какие-либо предложения, касающиеся обходных путей, пожалуйста, не стесняйтесь отвечать. Заранее большое спасибо!

4 ответа

Решение

Требование, что бинарный файл находится в каком-то определенном каталоге, кажется мне странным. Пока бинарный файл найден в PATH, все должно работать. Вместо этого вы можете попытаться прочитать файл данных из текущего рабочего каталога, то есть каталога, в котором находится пользователь при запуске программы.

Если вы не хотите, чтобы пользователи всегда копировали файл данных вокруг вас, вы можете выполнить поиск в нескольких местах по умолчанию, а затем использовать первое место, где найден файл, например, текущий рабочий каталог, затем $HOME/.your_program/file.dat и, наконец, /usr/local/share/your_program_name/file.dat или что-то в этом роде.

Редактировать Если, однако, вы хотите продолжить идти по этому неправильному пути, по крайней мере в Linux вы можете использовать readlink() (для этого вам, вероятно, нужно создать оболочку C, см. ISO C BINDING в последних компиляторах Фортрана), чтобы проверить /proc/self/exe символическая ссылка.

Кроме того, GETARG не является частью стандарта Fortran, поэтому вы полагаетесь на расширение поставщика (которое, по общему признанию, довольно широко поддерживается). Начиная с Fortran 2003, стандартной функцией для этого является встроенная функция GET_COMMAND_ARGUMENT.

Канаванин, вы нашли решение в это время? В g77 getarg(0,path) доставляет исполняемый файл с полным путем, но не в gfortran. Однако этот недостаток gfortran, по-видимому, относится только к конкретным окнам. Смотрите здесь, который демонстрирует функционирование getarg в оболочке bash...

--- corection: теперь я выяснил, что проблема не в GFORTRAN против G77, а в конкретной сборке. Последняя версия дистрибутива GCC / GFORTRAN (4.54) DJGPP (порт DOS) позволяет getarg(0, путь) доставлять полный путь перед [исполняемым файлом].exe. Символ разделения - "/", а не "\".

Я думаю, что это трудная проблема для решения в Фортране, и я думаю, что вы правы в своем подходе (поместите файл данных в тот же каталог, что и исполняемый файл). Фортрану нужно что-то подобное питону

os.path.dirname(os.path.realpath(sys.argv[0]))

К сожалению, fortran абсолютно ужасен для ввода / вывода, и ваш вопрос выделяет только один маленький аспект.

На тот случай, если кто-то другой бросит оружие и сочтет это тривиальным вопросом - рассмотрим случай, когда вы не знаете ОС, на которой люди будут запускать этот исполняемый файл, и не знаете его имени.

Мой, возможно, ужасный обходной путь - использовать INDEX для поиска "/". Если он возвращает ненулевое значение, то пользователь "должен" быть в системе Linux, поэтому используйте INDEX, чтобы убрать имя исполняемого файла, и вы получите свой путь. Затем найдите "\", и ​​если INDEX найдет что-то, предположите, OS=windows и удалите исполняемый файл.

В Digital Visual Fortran (и т. Д.) В Windows я делаю это так:

  SUBROUTINE GetFullExeName(FULLNAME,L)  


!******************************************************************************  
!  
!  Gets the full name of the current executing program.  
!  
!******************************************************************************  
      USE DFWIN  
      CHARACTER*(*) FULLNAME          ! full name  
      INTEGER       L                 ! length  
      L= GetModuleFileName(NULL,FULLNAME,LEN(FULLNAME))   ! windows API  
      FULLNAME(L+1:) = ' '  
      END  
Другие вопросы по тегам