Application development on Solaris OS using Sun Studio compilers and tools
Solaris Developer
ABOUT

We are the Solaris Developer Information Products Team:
Richard Friedman, David Lindt, Kami Shahi, Jyothi Srinath, Paul Echeverri, Ann Rice, Alta Elstad, Susan Morgan, Frank Jennings

DOCUMENTATION
»Solaris OS
»Sun Studio Compilers/Tools

ARTICLES
»Solaris OS
»Sun Studio Compilers/Tools

DOWNLOADS
»Solaris OS
»Sun Studio Compilers/Tools

RECENT ENTRIES
Archives
Click me to subscribe
Search

Links
 

Today's Page Hits: 39

« Sun Studio 12 IDE... | Main | C and C++ Technical... »
Friday Jun 22, 2007
New Article: Fortran Library Functions - How To Call Them

HOW TO CALL A LIBRARY FUNCTION OR SUBROUTINE FROM FORTRAN

by Michael Ingrassia, Fortran Compiler Group, Sun Microsystems

The Fortran language, both the standard language adhered to by all vendors and the extended language offered to Sun customers, contains several different models for how to call library functions. Confusion can result if you aren't clear about which model you should use for the particular library function you are calling. In this paper we try to describe the different models and provide examples of what might go wrong.

In general, any function found in a library can be called from Fortran. (Subroutines are rarer; for convenience we'll consistently refer to functions in this article where we should properly say function/subroutine). Here's a recipe for how to do it, which contains several specific recommendations for good coding practices.

To start , gather the following information:

Depending on what you find, there are 5 different models determining how to properly call this function:

Lets look at each situation in detail.

The function is a standard Fortran intrinsic. (For example, COS(x) )

This means that the Fortran standard defines the spelling of the function name, and prescribes what it should do. The function will be spelled the same way and work the same way on any standard-conforming Fortran compiler.

In this case, do not declare the function return type. And, for maximum portability, you should declare the function an intrinsic with an INTRINSIC statement:

INTRINSIC COS

Read the man page for the function (3F) and call the function with correctly typed arguments.

Example:

INTRINSIC COS
PRINT *, COS(0.01D0)
END

Things that could go wrong here:

INTRINSIC FOO
PRINT *, FOO(0.01D0)
END

% f95 t.f
INTRINSIC FOO

^ "t.f", Line = 1, Column = 12: ERROR: "FOO" is not an intrinsic routine.

The error message will be more obscure if you didn't include the INTRINSIC statement, which is one reason for recommending it.

The function is a Fortran intrinsic which isn't standard. (For example, CBRT(x) )

The Fortran standard permits processors to define additional intrinsics beyond those prescribed in the standard. They behave much the same way as standard intrinsics, except that they are not guaranteed to be portable to or from other Fortran compilers.

In this case, again, do not declare the function return type. And, for maximum portability, you should include declare the function an intrinsic with an INTRINSIC statement:

Example:

INTRINSIC CBRT
PRINT *, CBRT(27.0)
END

You can tell that this is a non-standard intrinsic by compiling with the -ansi flag:

% f95 t.f -ansi
PRINT *, CBRT(27.0)
^ "t.f", Line = 2, Column = 18: ANSI: Intrinsic "CBRT" is an extension to the Fortran standard.

Things that could go wrong here:

INTRINSIC FOO
PRINT *, FOO(0.01D0)
END

% f95 t.f
INTRINSIC FOO
^ "t.f", Line =
1, Column = 12: ERROR: "FOO" is not an intrinsic routine.

The error message will be even more obscure if you didn't include the INTRINSIC statement, which is one reason for recommending it.

INTRINSIC SDOT
REAL X(3), Y(3)
DATA X /1.,1.,1./
DATA Y /2.,2.,2./

PRINT *, SDOT(3, X, 1, Y, 1)
END

% f95 t.f -xknown_lib=blas1
% a.out
6.0

 

The function is not an intrinsic, but is supplied with the Fortran run-time libraries. (For example, DRAND(n) )

In this case, include the correct declaration of the function return type. For maximum portability, you should declare the function with an EXTERNAL statement:

EXTERNAL DRAND

Read the man page for the function (3F) and call the function with correctly typed arguments.

Example:

EXTERNAL DRAND
REAL*8 DRAND
PRINT *, 'Random number between 0.0 and 1.0: ',DRAND(1)
END

Things that could go wrong here:

EXTERNAL DRAND
PRINT *, 'Random number between 0.0 and 1.0: ',DRAND(1)
END

% a.out
Random number between 0.0 and 1.0: 1.7437383 ! WRONG number out of range

The function is not an intrinsic, nor is it supplied with the Fortran run-time libraries, but it is documented as a Fortran-callable function. (for example, SDOT(n,X,nx,Y,ny)

Sometimes we say that such a function "has a Fortran binding".

In this case, include a correct declaration of the function return type. For maximum portability, you should declare the function with an EXTERNAL statement:

EXTERNAL SDOT

Read the man page for the function and call the function with correctly typed arguments. Explicitly Link the program with the library containing the function.

Example:

EXTERNAL SDOT
REAL X(3), Y(3)
DATA X /1.,1.,1./
DATA Y /2.,2.,2./

PRINT *, SDOT(3, X, 1, Y, 1)
END

% f95 t.f -lsunperf
% a.out
6.0

Note that because this is documented as being a Fortran callable function, there was no need to worry about spelling issues such as trailing underscores in the linker name of the function. This was done by the library provider.

libsunperf is not normally one of the Fortran run-time libraries, and you must take extra steps to link with it.

Note that SDOT is a bit of a chameleon; it can be used as an intrinsic function if you use the -xknown_lib flag. But that is somewhat unusual; what is described here is the standard model for how to call Fortran-callable functions outside the Fortran run-time.

Things that could go wrong here:

For the above program, if libsunperf is not linked into the program, you will get

% f95 t.f
Undefined first referenced
symbol in file
sdot_ t.o
ld: fatal: Symbol referencing errors. No output written to a.out

Sometimes including complete interface blocks is advisable. It is easiest if the API supplier gives you a file to include which contains the recommended interface blocks.

The function is not an intrinsic, nor is it supplied with the Fortran run-time libraries, and the library provider does not document it as callable from Fortran. (For example ELF_VERSION(n))

Nonetheless, the function can be called from Fortran, but extra steps must be taken. You should also worry about whether the function is committed to be part of future architectures you will be building under. (Sometimes this is called the "stability level" of the interface.)

In this case, include a correct declaration of the function return type, and declare the function with the BIND(C) attribute. Include an actual interface block for the function. In addition to letting you accommodate C/Fortran differences using BIND(C), you will be able to describe the expected calling sequence. Explicitly link the program with the library containing the function.

Example:

USE, INTRINSIC :: ISO_C_BINDING

INTERFACE
FUNCTION ELF_VERSION(VER)
USE, INTRINSIC :: ISO_C_BINDING
INTEGER(C_INT), BIND(C) :: ELF_VERSION
INTEGER(C_INT), VALUE :: VER
END FUNCTION
END INTERFACE

INTEGER(C_INT), PARAMETER :: EV_NONE = 0
PRINT *, 'You linked with elf version ',ELF_VERSION(EV_NONE)
END

% f95 t.f -lelf
% ldd a.out | grep elf
libelf.so.1 => /usr/lib/libelf.so.1
% a.out
You linked with elf version 1

Note that a function interface had to be manually constructed to correspond to the documented API for elf_version in the elf_version(3ELF) man page:

unsigned elf_version(unsigned ver);

At that, the correspondence is imperfect; C_INT is made to stand in since C_UNSIGNED is not defined by the standard. Note that the standard syntax (BIND(C)) replaces previously recommended ways to call functions without a Fortran binding.

Things that could go wrong:

Functions do occasionally move between the various categories, usually upward (to models earlier in this list) since the models are given in order of increasing fussiness.


Posted at 02:49PM Jun 22, 2007 by Richard Friedman in Compilers  | 

Comments:

Post a Comment:
Comments are closed for this entry.