Organized library with Fortran functions
I am trying to make a library of useful functions. I yet don't know much about this, but apparently most of them, if not all, need to be included in a module (or in a interface inside the program, but since the point of this is to make a library, that doesn't seem to be a choice) or else the programs in which I'll use them won't recognize them.
I could make a long file with one module including all this functions, but I would like to keep the different functions in different short files. If I do this, however, I would have to make a different module for each function, and If I want to use them all in a program, I would have a very long USE
declaration list (not to mention the number of .mod files that would be produced).
The only possible solution for this I could come up with, was to make another module with just the USE
declarations for all other modules, but I think there must be another way to have a library containing functions that is not so far fetched.
Also, why is it that I have this problem with functions but not with subroutines? Is it because the command CALL
immediately identifies the line as a subroutine call whereas functions are called just by name with no command to tell the compiler "hey, this is a function", so it has to know what is a function and what not beforehand?
I am including an example (following the instructions in http://www.oceanographers.net/forums/showthread.php?378-How-to-make-a-FORTRAN-library, and using the correct 'path').
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
Command Line
> gfortran -c TestFunc.F90 -o TestFunc.o
> ar ruv libmylib.a *.o
> gfortran TestProg.F90 -o开发者_StackOverflow社区 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
My recommendation is to place both your functions and subroutines into a module, then use that module. Place ones that are logically related into the same module. Using one module per procedure seems very inconvenient -- why do you prefer this approach? The reason to place procedures (functions and subroutines) into a module and then "use" that module is that it makes the interface "explicit" so that the compiler can check consistency between the actual arguments in call and the dummy arguments of the procedure. This will find many types of bugs and save effort in your programming. It is easy and automatic compared to writing a declaration ("interface"). You don't have to write the procedure declaration AND the interface, and you don't have to keep them consistent when revisions are made. Yes, the "call" statement is helping the compiler identify subroutines, but the advantage of making the interface explicit via a module needs the module for both function and subroutine.
EDIT to answer comment: Yes, even if the procedures are being placed into a library, I'd place them into a single module. If the procedures are totally unrelated, then they probably belong in separate libraries and separate modules. If related, then in the same library and the same module. Fortran provides features to manage possible "issues" with having many procedures in the same module: you can make clear which procedures you are using in a "use" statement and avoid name clashes by using an "only" clause, listing only the procedures that are used. You can even rename a procedure that you want to use if the default name clashes with another name.
You don't need to put subroutines in modules in order to make a library. What I usually do is have subroutines in separate files, build object files (.o) out of them, and then archive them into a library, e.g.:
ar ruv mylib.a *.o
Then all it takes is to specify mylib.a during linking with the main program which calls the subroutine. It does not make a difference whether your procedure is a subroutine or a function.
EDIT1: Your main program needs to have a function declaration:
PROGRAM TestProg
IMPLICIT NONE
INTEGER :: sumnum
WRITE(6,*) SumNum(2,2)
STOP;END PROGRAM
Then:
gfortran -c *.f90
ar ruv mylib.a testfunc.o
gfortran testprog.o -o x mylib.a
When I run x, I get correct output.
To answer the question regarding the difference between function and subroutine with the implicit interfaces: functions are used like variables, and there type needs to be known, thus you need to declare them with the external attribute. However, I also would strongly recommend M. S. B.s answer, that you should put everything into modules, by this you get explicit interfaces for all your routines, and such problems are avoided. One more comment, the return statement in your sample code is unnecessary, as well as the stop.
精彩评论