1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
|
CPGPLOT - An ANSI-C interface to the FORTRAN PGPLOT library.
-----------------------------------------------------------
Background
----------
Calling PGPLOT directly from C is a messy, difficult and unportable
exercise. This is due to the lack of a universal set of inter-language
calling conventions, and to the lack of a standard on how FORTRAN
LOGICAL and CHARACTER types are represented in terms of basic machine
types. Furthermore, since C implements call-by-value argument passing
semantics, whereas FORTRAN uses pass-by-reference, there is the added
complication that literal values must be sent indirectly by way of
references to dummy variables.
The CPGPLOT library adds an intermediate level of wrapper functions
between C programs and the PGPLOT library. These functions hide the
system dependencies of calling PGPLOT behind a system independent
interface.
USING THE LIBRARY
-----------------
The most important thing to remember when using the CPGPLOT interface
library is to include the library header file, cpgplot.h at the top of
all C files containing calls to the library. Without this file, the
functions will not be correctly prototyped and your code will not
work.
IMPORTANT CONVENTIONS:
1. The names of the C interface library functions are the same as
their PGPLOT counterparts, but are prefixed with a 'c' and written
in lower case.
2. The interface implements pass-by-value argument passing semantics.
This removes the need for dummy variables, except where arguments
are used to return values.
3. Where PGPLOT expects LOGICAL arguments, the C interface requires
(int) arguments. Integral zero is interpreted as FORTRAN .FALSE.
and non-zero as FORTRAN .TRUE..
FORTRAN call. C equivalent call(s).
-------------- ----------------------------
PGASK(.FALSE.) cpgask(0)
PGASK(.TRUE.) cpgask(1) or cpgask(2) etc..
4. Functions that take strings as input require normal C '\0'
terminated (char *) strings.
5. Arguments that are used to return FORTRAN strings, must be treated
with care. FORTRAN doesn't understand '\0' termination of strings
and instead requires that the dimension of the character array be
specified along with the array. The interface handles this
transparently for input-only strings by using strlen() to determine
the length of the string, but for return string arguments it needs
to be told the length available in the passed char array.
Fortunately all PGPLOT routines that return such strings also have
an argument to return the unpadded length of the return string. In
CPGPLOT, you must initialize this argument with the dimension of
the string array that has been sent. In the prototypes listed in
cpgplot.h the length arguments are distinguishable by virtue of
their having the name of the string to which they relate, postfixed
with "_length". For example, the PGPLOT routine PGQINF() is
prototyped as:
void cpgqinf(char *item, char *value, int *value_length);
Where the 'value_length' argument is the length argument for the
string argument 'value'.
For example, to write a C function to return 1 if a PGPLOT device
is open, or 0 otherwise, one could write.
#include "cpgplot.h"
int pgplot_is_open(void)
{
char answer[10]; /* The PGQINF return string */
int answer_len = sizeof(answer); /* allocated size of answer[] */
cpgqinf("STATE", answer, &answer_len);
return strcmp(answer, "YES") == 0;
}
Note that the dimension, sent as the third argument, is the total
number of characters allocated to the answer[] array. The
interface function actually subtracts one from this when it tells
PGPLOT how long the string is. This leaves room for the interface
function to terminate the returned string with a '\0'. All returned
strings are terminated in this manner at the length returned by
PGPLOT in the length argument.
LIMITATIONS
-----------
Note that PGPLOT procedures that take FORTRAN SUBROUTINEs or FUNCTIONs
as arguments are not represented in the CPGPLOT library. Such
procedures can not be handled on most systems.
RESIDUAL MACHINE DEPENDENCIES
-----------------------------
Many system vendors say that if you call FORTRAN functions that do any
I/O, you should have a FORTRAN main program, so that the FORTRAN I/O
module gets correctly initialized. Since PGPLOT uses FORTRAN I/O, this
applies to C programs that call PGPLOT.
Linking a C PGPLOT program.
--------------------------
Since FORTRAN usually has to be linked with a lot of support
libraries, it is usually most convenient to use the FORTRAN compiler
to link your C program. If your compiler is not the system-supplied
compiler, then it is unlikely that the FORTRAN compiler will cite the
correct C run-time library to the linker. This means that you will
have to do it yourself. For instance under SunOS 4.x, I use gcc, because
the the native C compiler is a pre-ANSI variant. Code generated by
this compiler must be linked with libgcc.a. Where this library is
located is system dependent, but is often placed in either
/usr/local/lib or /usr/local/lib/gcc-lib/machine_type/gcc_version/.
In either case, under SunOS/Solaris, if both this path and the path of
the installation directory of the pgplot libraries exist in your
LD_LIBRARY_PATH environment variable, you can link your program with a
statement like:
f77 -o blob *.o -lcpgplot -lpgplot -lX11 -lgcc -lm
Other systems will have a different name for the LD_LIBRARY_PATH
variable, but in general it would be set with something like:
"/usr/local/pgplot:/usr/local/lib/gcc-lib/sparc-sun-solaris2.3/2.5.8/"
Under csh or tcsh, use the setenv command to set this:
setenv LD_LIBRARY_PATH "..."
Under sh, bash, ksh:
LD_LIBRARY_PATH="..."
export LD_LIBRARY_PATH
On systems that don't support such a variable, you will have to
explicitly specify both the libraries and their paths. For example,
under SunOS:
f77 -o blob *.o -L/usr/local/pgplot -lcpgplot -lpgplot -lX11 \
-L/usr/local/lib/gcc-lib/sparc-sun-solaris2.3/2.5.8/ -lgcc -lm
PORTING TO A NEW SYSTEM
-----------------------
Not all systems are supported by the interface library. This is both
because we don't have many of the systems here that we would need to
create and test any such configuration, and because not all systems
can be supported.
The program that creates the library for each system is called pgbind
(situated in the pgplot/cpg/ directory). To determine whether your
system can be supported by this program, compile it with an ANSI-C
compiler and run it with no arguments. It will list the available
configuration options.
If the current version of pgbind does not provide sufficient options
to support your system, send us details of how your FORTRAN compiler
acts. We need to know:
1. In what form does the FORTRAN compiler export FORTRAN symbol names
to the linker. Are the symbol names exported in lower-case, upper
case, or in the case that FORTRAN symbols are declared with, and
does it prefix or postfix any character or string to symbol names?
2. If you EQUIVALENCE a FORTRAN LOGICAL variable with a FORTRAN
INTEGER variable, what are the values of the integer variable when
the logical variable is set first to .FALSE. and then to .TRUE.?
3. How does your FORTRAN compiler pass strings?
UNIX CONFIGURATION
------------------
If your system is a UNIX system, configured using the makemake script,
and it is possible to support your system with one of the available
templates, plus zero or more feature overrides, then list the option
arguments as the string assigned to the optional PGBIND_FLAGS variable
in your system configuration file, re-run the makemake script and type:
make cpg
This should create the cpgplot.a library, its header file cpgplot.h
and a demo program called cpgdemo. If the demo program runs, you are
in business. Please tell us what PGBIND_FLAGS string you used so that
we can incorporate it in the system configuration file for the next
PGPLOT release.
NON-UNIX SYSTEMS
----------------
If your system is not a UNIX system, then you will need to find a way
to extract specific lines from the PGPLOT source code. Most of the pg*.f
files in the src PGPLOT subdirectory contain one or more lines that
start with C%. These are C prototypes, which should be extracted
complete with the C% prefix and placed, one line after another in a
single file. The result of processing this file with pgbind will be a
set of C files - one per interface function - and the cpgplot.h
library header. Compile the functions and place them in an
appropriately named library.
PROBLEMS
--------
The cpgplot library has not been thoroughly tested, and the
pgbind configurations of some systems have not been tested at all. If
you have any problems, please send me a list of symptoms, and I will
endeavor to solve them through modifications to the pgbind program.
HISTORY
-------
The pgbind program that creates the library header and interface
functions was written by Martin Shepherd. This followed in the
footsteps of an earlier program called cbind, written by Jim Morgan.
Martin Shepherd (mcs@astro.caltech.edu)
|