As discussed in the preceding section, PLplot's integer representation is a
PLINT and its floating point representation is a PLFLT. To the
Fortran 95 user, this most commonly translates to a type
integer
and
type real
, respectively. This is somewhat system dependent (and up to
the installer of the package) so you should check the release notes to be
sure, or just try it and see what happens.
Because the PLplot kernel is written in C, standard C syntax is used in the
description of each PLplot function. Thus to understand this manual it is
helpful to know a little about C, but fortunately the translation is very
easy and can be summarized here. As an example, the routine
plline
call from C would look like:
plline(n,x,y);
The argument n
is the number of points that make
up the line and the arguments x
and y
are arrays of floating-point numbers containing the x- and y-coordinates of the
points.
In C you need to specify the array dimensions explicitly, whereas in
Fortran 95 the array dimension can be implicit, which leads to less
mistakes. The interface to plline
would ideally look
like this:
interface subroutine plline(x,y) real, dimension(:) :: x, y end subroutine plline end interface
There is one slight complication: PLplot can be compiled with either
single-precision reals or double-precision reals. It is very
important to keep the variables that are passed to PLplot in
the same precision. Fortunately, Fortran 95 provides the
KIND
mechanism for this.
The actual interface to plline
therefore looks like:
interface subroutine plline(x,y) real(kind=plflt), dimension(:) :: x, y end subroutine plline end interface
The parameter plflt
is defined in the
PLplot
module and should be used consistently with
all real variables that you pass to PLplot routines.
Here is a short overview of how C data types correspond to Fortran 95 data types:
PLFLT | real(kind=plflt) |
PLINT | integer |
char * | character |
PLFLT * | real(kind=plflt) or real(kind=plflt), dimension(:) |
PLFLT ** | real(kind=plflt), dimension(:,:) |
"string" | 'string' |
array[0] | array(1) |
In C there are two ways to pass a variable --- by value (the default) or by
reference (pointer), whereas only the latter is used by Fortran 95.
Therefore when you see references in the text to either an ordinary
argument or a pointer argument (e.g. *data
), you simply use an
ordinary Fortran 95 variable or array name (the interfacing
routines take care of any transformations that may be necessary).
The PLplot library comes with a set of Fortran 95 interface routines that allow the same call semantics (usually) regardless of whether calling from C or Fortran 95. In some cases, the Fortran 95 interface uses implicit array dimensions, so that it has fewer arguments than the C counterpart.
These “stub” routines handle transforming the data from the normal Fortran 95 representation to that typically used in C. This includes:
Variables passed by value instead of by reference.
Fortran 95 passes all subroutine arguments by reference, i.e., a pointer to the argument value is pushed on the stack. In C all values, except for arrays (including char arrays), are passed by value, i.e., the argument value itself is pushed on the stack. The stub routine converts the Fortran 95 call by reference to a call by value. As an example, here is how the plpoin stub routine works. In your Fortran 95 program you might have a call to plpoin that looks something like
real(kind=pllft), dimension(6) :: x, y x = ... y = ... call plpoin(x,y,9)
where x and y are arrays with 6 elements and you want to plot symbol 9.
The routine plpoin
calls the underlying routine
plpoinf95
:
subroutine plpoin( x, y, code ) integer :: code real(kind=plflt), dimension(:) :: x, y call plpoinf95( size(x), x, y, code ) end subroutine plpoin
This takes care of the size of the arrays - it is not possible to transfer this information to C in an implicit way.
The routine plpoinf95 is implemented in C to take care of the question pass by value or pass by reference: [2]
#include "plplot/plstubs.h" void PLPOIN(n, x, y, code) PLINT *n, *code; PLFLT *x, *y; { c_plpoin(*n, x, y, *code); }
All this stub routine does is convert the number of points
(*n
and the
symbol *code
to call by value (i.e. pushes their value on the stack)
and then calls the C plpoin library routine.
Get mapping between Fortran 95 and C namespace right (system dependent).
The external symbols (i.e. function and subroutine names) as you see them in your program often appear differently to the linker. For example, the Fortran 95 routine names may be converted to uppercase or lowercase, and/or have an underscore appended or prepended. This translation is handled entirely via redefinition of the stub routine names, which are macros. During the build process, the properties of the build environment are detected and the correct compiler options are used.
Once the name translation is established during installation, name translation is completely transparent to the user.
Translation of character string format from Fortran 95 to C.
Fortran 95 character strings are passed differently than other quantities, in
that a string descriptor is pushed on the stack along with the string
address. C doesn't want the descriptor, it wants a NULL terminated string.
For routines that handle strings two stub routines are necessary, one
written in Fortran 95 and one written in C. Your Fortran 95 program calls the
Fortran 95 stub routine first. This stub converts the character string to a
null terminated integer array and then calls the C stub routine. The C
stub routine converts the integer array (type long
) to the usual C
string representation (which may be different, depending on whether your
machine uses a big endian or little endian byte ordering; in any case the
way it is done in PLplot is portable). See the plmtex
stubs for an
example of this.
Note that the portion of a Fortran 95 character string that exceeds 299
characters will not be plotted by the text routines (plmtex
and plptex
).
Multidimensional array arguments are changed from row-dominant to column-dominant ordering through use of a temporary array.
In Fortran 95, arrays are always stored so that the first index increases most rapidly as one steps through memory. This is called “row-dominant” storage. In C, on the other hand, the first index increases least rapidly, i.e. “column-dominant” ordering. Thus, two dimensional arrays (e.g. as passed to the contour or surface plotting routines) passed into PLplot must be transposed in order to get the proper two-dimensional relationship to the world coordinates. This is handled in the C stub routines by dynamic memory allocation of a temporary array. This is then set equal to the transpose of the passed in array and passed to the appropriate PLplot routine. The overhead associated with this is normally not important but could be a factor if you are using very large 2d arrays.
This all seems a little messy, but is very user friendly. Fortran 95 and C programmers can use the same basic interface to the library, which is a powerful plus for this method. The fact that stub routines are being used is completely transparent to the Fortran 95 programmer.
For more information on calling PLplot from Fortran 95, please see the
example Fortran 95 programs (/examples/f95/x??f.f
)
distributed
with PLplot.
[2]
PLPOIN
is a macro that get translated into the correct name
for this routine - various Fortran compilers use different conventions, such as
adding an underscore or translating the name into capitals.