Организованная библиотека с функциями Фортрана - PullRequest
2 голосов
/ 28 сентября 2011

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

Я мог бы сделать длинный файл с одним модулем, включающим в себя все эти функции, но я хотел бы сохранить разные функции в разных коротких файлах. Однако, если я сделаю это, мне придется создать разные модули для каждой функции, и если я захочу использовать их все в программе, у меня будет очень длинный список объявлений USE (не говоря уже о числе. мод файлы, которые будут производиться).

Единственное возможное решение, которое я мог придумать, - это создать еще один модуль с объявлениями USE для всех остальных модулей, но я думаю, что должен быть другой способ иметь библиотеку, содержащую функции, которые не так притянуто за уши.


Кроме того, почему у меня такая проблема с функциями, а не с подпрограммами? Это потому, что команда CALL сразу идентифицирует строку как вызов подпрограммы, тогда как функции вызываются просто по имени, без команды, чтобы сказать компилятору «эй, это функция», поэтому она должна знать, что такое функция и что не заранее?


Я включил пример (следуя инструкциям в http://www.oceanographers.net/forums/showthread.php?378-How-to-make-a-FORTRAN-library, и используя правильный «путь»).

TestFunc.F90

FUNCTION SumNum(nNum1,nNum2) RESULT(nResult)  
IMPLICIT NONE  
INTEGER,INTENT(IN) :: nNum1,nNum2  
INTEGER            :: nResult  

nResult=nNum1+nNum2  

RETURN;END FUNCTION  

TestProg.F90

PROGRAM TestProg  
IMPLICIT NONE  

WRITE(6,*) SumNum(2,2)  

STOP;END PROGRAM  

Командная строка

> gfortran -c TestFunc.F90 -o TestFunc.o  
> ar ruv libmylib.a *.o  
> gfortran TestProg.F90 -o Test.x -L/path -lmylib.a

TestProg.F90:6.12:  

    WRITE(6,*) SumNum(2,2)  
               1  
Error: Function 'sumnum' at (1) has no IMPLICIT type  

Ответы [ 3 ]

7 голосов
/ 29 сентября 2011

Моя рекомендация - поместить ваши функции и подпрограммы в модуль, а затем использовать этот модуль. Поместите те, которые логически связаны в один и тот же модуль. Использование одного модуля на процедуру кажется очень неудобным - почему вы предпочитаете такой подход? Причина размещения процедур (функций и подпрограмм) в модуле и последующего «использования» этого модуля заключается в том, что он делает интерфейс «явным», чтобы компилятор мог проверить согласованность между фактическими аргументами в вызове и фиктивными аргументами процедуры. Это позволит найти много типов ошибок и сэкономить усилия при программировании. Это просто и автоматически по сравнению с написанием декларации («интерфейс»). Вам не нужно писать объявление процедуры И интерфейс, и вам не нужно поддерживать их согласованность при внесении изменений. Да, оператор "call" помогает компилятору идентифицировать подпрограммы, но преимущество явного интерфейса через модуль требует модуля как для функции, так и для подпрограммы.

РЕДАКТИРОВАТЬ, чтобы ответить на комментарий: Да, даже если процедуры помещаются в библиотеку, я бы поместил их в один модуль. Если процедуры совершенно не связаны, то они, вероятно, принадлежат отдельным библиотекам и отдельным модулям. Если связаны, то в той же библиотеке и в том же модуле. Fortran предоставляет функции для управления возможными «проблемами» с наличием множества процедур в одном модуле: вы можете уточнить, какие процедуры вы используете в выражении «use», и избежать столкновений имен, используя предложение «only», перечисляя только те процедуры, которые используются. Вы даже можете переименовать процедуру, которую хотите использовать, если имя по умолчанию конфликтует с другим именем.

4 голосов
/ 28 сентября 2011

Вам не нужно помещать подпрограммы в модули для создания библиотеки. Обычно я делаю подпрограммы в отдельных файлах, строю из них объектные файлы (.o) и затем архивирую их в библиотеку, например ::10000

ar ruv mylib.a *.o

Тогда все, что требуется, это указать mylib.a во время соединения с основной программой, которая вызывает подпрограмму. Не имеет значения, является ли ваша процедура подпрограммой или функцией.

EDIT1: Ваша основная программа должна иметь объявление функции:

PROGRAM TestProg  
IMPLICIT NONE  
INTEGER :: sumnum

WRITE(6,*) SumNum(2,2)  

STOP;END PROGRAM  

Тогда:

gfortran -c *.f90
ar ruv mylib.a testfunc.o
gfortran testprog.o -o x mylib.a

Когда я запускаю x, я получаю правильный вывод.

0 голосов
/ 29 сентября 2011

Чтобы ответить на вопрос о разнице между функцией и подпрограммой с неявными интерфейсами: функции используются как переменные, и тип должен быть известен, поэтому вам необходимо объявить их с внешним атрибутом. Однако я также настоятельно рекомендую ответить М.С.Б., чтобы вы все помещали в модули, тем самым вы получаете явные интерфейсы для всех ваших подпрограмм, и таких проблем можно избежать. Еще один комментарий, оператор возврата в вашем примере кода не нужен, также как и остановка.

...