Proposal for an OpenGL FORTRAN Binding
September 16, 1994


		Proposal for an OpenGL FORTRAN Binding
			    Allen Akin
			September 16, 1994



If you're most interested in the FORTRAN binding as viewed by an
application developer, then read the sections titled "Overview" and
"Binding".  If you're considering implementing the binding, then you
should read the "Summary of Issues" section carefully.

Note that the implementation of the binding is highly
system-dependent.  It's likely that SGI won't be able to supply a
sample version of anything other than the ".h" files which define
manifest constants.  If you want to supply an OpenGL library to your
FORTRAN customers, you'll probably have to implement the wrapper
routines from scratch.




Overview

1.  Scope.

    This proposal covers FORTRAN bindings for the core of OpenGL and
    for the GLU (OpenGL Utilities).

    It does not cover the GLX API, because we're told there is no
    consensus on a FORTRAN binding for the Xlib routines and data
    structures needed by GLX.  It also does not cover the analogous
    support routines for Microsoft Windows, because Microsoft has not
    yet published a C binding to serve as a model.

2.  Compatibility with FORTRAN standards.

    The FORTRAN binding is intended to work with standard Fortran 90
    implementations, as well as standard FORTRAN 77 implementations
    with some extensions that we believe are universally available.

3.  Identifiers in C and FORTRAN bindings.

    The identifiers in the FORTRAN binding are the same as those in the
    C binding, with the exception that the "gl" prefix is changed to
    "fgl" and the "GL" prefix is changed to "FGL".  External symbols
    must use "fgl" rather than "gl" to avoid name-space clashes in some
    systems that implement the OpenGL FORTRAN binding as a wrapper
    around the OpenGL C binding.  We changed the other names for
    consistency and to prepare for potential problems with long
    identifiers.

4.  Parameter lists and return types in C and FORTRAN bindings.

    In general the parameter lists and return types of routines in the
    FORTRAN binding are identical to those of the corresponding
    routines in the C binding (subject to the data type substitutions
    described next).

5.  Data types in C and FORTRAN bindings.

    Types in the OpenGL C binding will be translated to FORTRAN types
    as follows:

	GLbyte                          INTEGER*1
	GLshort                         INTEGER*2
	GLint, GLsizei                  INTEGER*4
	GLfloat, GLclampf               REAL*4
	GLdouble, GLclampd              REAL*8
	GLubyte                         INTEGER*1
	GLboolean                       LOGICAL*1
	GLushort                        INTEGER*2
	GLuint, GLenum, GLbitfield      INTEGER*4
	GLvoid                          no equivalent needed
	pointers (see below)            CHARACTER*8

6.  Letter case in code and documentation.

    Letter case is not significant in the FORTRAN binding.  This is
    required by the relevant FORTRAN standards.  For the sake of
    consistency with the documentation describing the C binding,
    identifiers in the FORTRAN binding will be documented in mixed
    case.  This is not the usual FORTRAN practice, but it seems to be
    the best compromise for OpenGL.

7.  Packaging.

    Manifest constants and declarations of external subprograms will be
    packaged in include files named "fgl.h" (for the OpenGL core) and
    "fglu.h" (for the OpenGL Utilities) which will reside in the same
    directory as "gl.h" and "glu.h" used by the C binding.

    Since nearly all systems will implement the FORTRAN binding as a
    set of wrappers that invoke routines in the C binding, I think it
    will be most convenient if the wrappers are included in the same
    libraries as the corresponding C routines.  This eliminates the
    need to link with multiple libraries, and may simplify library
    construction, distribution, and documentation.




Summary of Issues

Implementors should read this section carefully, because it describes a
number of potential problems that might be encountered when building a
FORTRAN binding.

In the following paragraphs, the term "respondents" refers to the
Usenet readers who replied to a query posted in the newsgroups
comp.graphics.opengl and comp.lang.fortran.

1.  Case Sensitivity.

    All respondents agreed that case must not be significant.  (That
    is, the OpenGL binding should not include identifiers that differ
    only in case.)  This is not a problem for OpenGL.

    Apparently all current FORTRAN compilers accept mixed-case input.
    However, respondents disagreed about the desirability of mixed-case
    identifiers.

2.  Use of Underscores.

    Fortran 90 specifically allows underscores in identifiers, provided
    that the underscores do not appear as the first or last character.
    This is not a problem for OpenGL.

    All respondents indicated that underscores are supported in their
    current workstation development environments.

3.  Identifier Length Limits.

    Fortran 90 requires that identifiers be distinguishable in their
    first 31 characters.  The C binding for OpenGL meets this
    requirement.

    The C binding includes identifiers that are longer than 31
    characters (GL_CURRENT_RASTER_TEXTURE_COORDS and
    GL_CURRENT_RASTER_POSITION_VALID).  We do not know whether some
    FORTRAN compilers will object to identifiers of this length.

    There seems to be no consensus about the maximum length for
    external identifiers (those that are visible to the linker).  The
    longest such identifiers in the C binding appear to be
    glGetTexLevelParameteriv and glGetTexLevelParameterfv, at 24
    characters.  23 characters must be significant to distinguish the
    two names.  Several respondents indicated that they would not
    expect linkers to be able to handle such lengths.  However, none
    identified a system that they knew would fail.  FORTRAN
    environments are probably not any more restrictive than C
    environments, so if 24-character externals are acceptable in C on a
    given system then they are likely to be acceptable in FORTRAN.

4.  External Namespace Clashes.

    Some environments (e.g. Microsoft FORTRAN) have a general
    cross-language calling capability that allows FORTRAN applications
    to call the routines in the OpenGL C binding directly.
    Unfortunately, most systems lack this feature.  Therefore, I expect
    most vendors will implement the OpenGL FORTRAN bindings as a set of
    "wrapper" routines that call corresponding C routines.

    The issue is whether one can write a wrapper that allows a FORTRAN
    program to call a C routine, and guarantee that the wrapper can be
    invoked from FORTRAN using the name of the C routine.  If this is
    so, then the same routine names can be used in the FORTRAN and C
    bindings.  If this is not so, the FORTRAN binding must use distinct
    names.

    Apparently the usual way to solve this problem in UNIX environments
    is to have FORTRAN append an underscore to the names of external
    identifiers.  For example, a FORTRAN program would call
    "GLBEGIN(GL_POLYGON)" and the call would actually invoke an
    external routine named "GLBEGIN_".  This routine could be a wrapper
    which executes "glBegin(GL_POLYGON)" and thus invokes the regular
    OpenGL C routine.

    According to the respondents, VMS FORTRAN and UNICOS (Cray) FORTRAN
    environments do not handle external FORTRAN names in this way.  IBM
    (XLF) and HP do not handle external FORTRAN names in this way
    unless a compiler option is used.  Many respondents stated that
    they cannot use this option in all cases.

    Several respondents noted that *all* the external names in the C
    binding are mixed-case, whereas *all* external references from
    FORTRAN applications are in a single case (because compilers map
    the names to one case to enforce case-insensitivity).  This might
    allow the same names to be used for both bindings; all that is
    necessary is to ensure that the FORTRAN wrappers have appropriate
    single-case names.

    According to Burkhard Burow, author of CFORTRAN (a C <-> FORTRAN
    interfacing package), this technique works on all systems he's
    tried  *except* VMS.  He says the VMS linker is case-insensitive
    for FORTRAN modules, so the external names will conflict.

    Therefore it appears that we must use distinct names for the same
    OpenGL routine in the C and FORTRAN bindings.  This is why we
    changed the "gl" prefix in the C binding to "fgl" in the FORTRAN
    binding.

5.  Data Type Incompatibilities.

    Some data types in C may not be available in FORTRAN, or
    vice-versa.  The example cited most-often is the lack of "short" on
    Cray systems.  It appears that this is not a serious problem for
    the OpenGL binding, though it may be a problem for portability of
    applications that use such types.

    FORTRAN lacks support for unsigned arithmetic, so C unsigned
    integer types must be translated to FORTRAN signed integer types.
    This should not be a major problem.

    Pointer types are more awkward.  See below.

6.  Data Value Incompatibilities.

    Examples are the values of the FORTRAN LOGICAL type.  The FORTRAN
    values for .TRUE. and .FALSE. do not necessarily correspond to the
    C conventions of nonzero and zero.  At the moment, it appears that
    Microsoft FORTRAN is the only environment for which this may be a
    problem.  (MS FORTRAN uses only the least-significant byte to hold
    the LOGICAL value; the other bytes may contain arbitrary data.) For
    such systems, the wrapper routines must perform an appropriate
    conversion.

7.  Data Layout Incompatibilities.

    FORTRAN stores multidimensional arrays in column-major order, while
    C stores them in row-major order.  It appears that this is not a
    problem, since there are no multidimensional arrays in the C
    binding for OpenGL.

    There are no structs in the C binding, so handling structure layout
    is not an issue.

8.  Pointers.

    Pointer types are not generally available in FORTRAN 77.

    Use of pointers in parameter lists is not a problem; the wrapper
    routines can convert between FORTRAN and C calling conventions as
    needed.  No special pointer type is required.

    One core OpenGL routine (glGetString) and one GLU routine
    (gluErrorString) return pointers to character strings.  There is no
    simple way to support these routines in FORTRAN 77, where there are
    no means to dereference pointers or allocate memory dynamically.
    No matter how large a fixed-size buffer is used for the return
    value, it might be too small.  (Especially for glGetString, which
    can return an arbitrarily-long list of extension names.) Even if a
    return value is provided to indicate that the supplied buffer is
    too small, there is no portable way to allocate a larger one and
    try again.

    For now, we will simply declare these routines to return a
    CHARACTER*256 value.  (Some implementations of FORTRAN 77 limit the
    maximum length of a character string to 256.)  If developers are
    concerned about this, we can ask them to work around the problem by
    adding some assembly code to call the C versions of the routines,
    or we can write a small utility to deliver the strings one buffer
    at a time.

    Three GLU routines (gluNewNurbsRenderer, gluNewQuadric, and
    gluNewTess) return pointer values.  These routines are problematic,
    because their return values are compared to NULL, stored, and
    re-used by the application program.

    Some machines now support 64-bit pointers, so if these routines are
    to return actual pointers, they must return a FORTRAN object of at
    least that size.  CHARACTER*8 variables are an option, though they
    have an awkward representation for NULL.  REAL*8 variables are
    another option, though on some machines floating-point load and
    store operations may corrupt the value of the pointer or generate
    an exception.  INTEGER*8 variables are not available on all FORTRAN
    implementations.

    I think the right compromise is to represent pointers as variables
    of type CHARACTER*8.  This allows source code portability, makes
    implementation easy on both 32- and 64-bit machines, and makes the
    FORTRAN binding as similar to the C binding as possible.  The value
    of NULL is slightly awkward to construct on some FORTRAN 77
    implementations, but is easy to use once constructed:

		character*8 tessobj, NULL
		NULL = char(0) // char(0) ... // char(0)
		tessobj = fgluNewTess()
		if (tessobj .eq. NULL) ...

9. GL -> OpenGL Converter.

    One respondent requested a tool for converting GL-based FORTRAN
    programs to OpenGL.  At the moment there are no plans for such a
    tool.

10. Standards Committee Involvement.

    Many of the respondents raised this topic.  There appear to be
    three distinct issues.

    First, X3J3 and WG5 will *strongly* encourage the use of Fortran 90
    as a basis for new bindings.  Fortran 90 implementations are not
    yet widely available, so this approach has the disadvantage that it
    may not play well with existing development environments.

    Second, some existing FORTRAN standards set requirements for
    FORTRAN bindings.  The two that were cited are POSIX.9 (for rules
    about FORTRAN name spaces), and Fortran 90 ("Guidelines for
    Language Bindings.")

    Third, more than one respondent stated that X3J3 and WG5 will be
    annoyed if FORTRAN bindings are proposed without consulting them
    (or at least providing documentation for them to review).  This may
    be an issue for some licensees who are actively involved in
    standards work.

    Jose Oglesby, the Microsoft representative to X3J3, volunteered to
    act as liaison to the ARB if the OpenGL community decides to
    address these issues.














Binding

The full FORTRAN binding is many thousands of lines long, so we've
chosen to omit it from this proposal.  However, this section will
illustrate selected parts of the binding.

The definitions of manifest constants in the C binding translate to
INTEGER and PARAMETER statements in the FORTRAN binding.  For example:

	#define GL_ACCUM                            0x0100

becomes

	integer*4   FGL_ACCUM
	parameter ( FGL_ACCUM = 256 )


Types are converted according to the table in the Overview section.

We assume that assembly-language wrapper routines will handle the
conversion from FORTRAN calling conventions to C calling conventions.
This allows the FORTRAN calls can be inferred from the C calls with
very little effort:


	void glVertex3fv (const GLfloat *v);

	subroutine fglVertex3fv (v)
	real*4 v(3)



	void glColor3ub (GLubyte red, GLubyte green, GLubyte blue);

	subroutine fglColor3ub (red, green, blue)
	integer*1 red, green, blue


The C routines involving pointers are translated as follows:


	const GLubyte * glGetString (GLenum name);

	character*256 fglGetString (name)
	integer*4 name



	const GLubyte* gluErrorString (GLenum errorCode);

	character*256 fgluErrorString (errorCode)
	integer*4 errorCode



	GLUnurbsObj* gluNewNurbsRenderer (void);

	character*8 fgluNewNurbsRenderer()



	GLUtriangulatorObj* gluNewTess (void);

	character*8 fgluNewTess()



	GLUquadricObj* gluNewQuadric (void);

	character*8 fgluNewQuadric()


The types GLUnurbsObj*, GLUtriangulatorObj*, and GLUquadricObj* are all
translated to CHARACTER*8.  Variables of this type can be copied, passed
to other GLU routines, etc.  They can also be tested against a NULL
pointer value in exactly the same manner as C pointers.  We will define
the NULL value as char(0)//char(0)//...//char(0) (8 occurrences of
char(0)).  Note that a single char(0) is not sufficient, because FORTRAN
strings are blank-padded.

[end]