Skip to main content

IBM Research


Fortran Interface Primer

The Fortran interface allows NAO objects to be created, used and deleted from a Fortran program. The Fortran interface is functionally equivalent to the Raw interface, being Stub routines which turn around and call the Raw interface. There are two important issues that arose when we created this interface: how to generate names for the Fortran routines that call the Raw interface, and how to pass objects between C++ and Fortran. These are discussed in some detail below.

The Object Life Cycle

In an object oriented system, the user creates an object, manipulates it, and then deletes it. All objects that are created are initialized, and so we need a call to a object-specific routine called a constructor, that allocates and initializes storage. This is the first step in the life of an object, its birth if you will.

The constructor returns a pointer to an "object", in an integer*4 variable, which may be passed to other routines, simply by passing the integer as an argument to the routine. There is a special set of routines called member functions, which are thought of as belonging to the object. A member function is invoked with the object as the first object. So to retreive the Base Space Dimension of a geometrical object, G, we call NAFGetBaseSpaceDimension(G).

The final stage in an objects life is death, or destruction. (Cheerful analogy, eh? I didn't make it up.) This is done with the NAFDeleteObject subroutine. The object is not necessarily destroyed when this routine is called, since other objects or routines may have stored references to it. A reference is added with the NAFReferenceObject routine, and one reference is removed when NAFDeleteObject is invoked. When the reference count goes to zero, the object is deleted. This is a very simple scheme for doing garbage collection. It works rather well if there are no circular dependancies, and every one plays by the rules.

Here is a one of the example programs in the Fortran interface:


      program main

      integer*4 Ball
      integer*4 X
      integer*4 NAFCreateUnitBallAtOrigin
      integer*4 NAFCreateDoublePointOnManifold5d
      integer*4 M
      logical NAFManifoldIsItInChart

      Ball=NAFCreateUnitBallAtOrigin(5)
      X=NAFCreateDoublePointOnManifold5d(.1d0,.3d0,0.d0,-.02d0,0.d0)

      write(6,*)" Hey! Did you know that the point "
      call NAFPrintPointOnManifold(X,6)
      if(NAFManifoldIsItInChart(Ball,X))then
        write(6,*)" is inside"
       else
        write(6,*)" is not inside"
      endif
      write(6,*)" a five dimensional ball of radius 1 "
     *        //"centered at the origin?\n"

      call NAFDeleteObject(X)
      call NAFDeleteObject(Ball)
       
      call exit
      end

Naming conventions

All Fortran interface routines are prefixed with "NAF".
Constructors and NACreate... routines become NAFCreate...,
S=new NASphere()becomesS=NAFCreateSphere()
P=NACreatePolyhedron("Tetrahedron")becomesP=NAFCreatePolyhedron("Tetrahedron")
Destructors are called by way of NAFDeleteObject().
S->unReference()becomesNAFDeleteObject(S)
P->unReference()becomesNAFDeleteObject(P)
Member functions are provided at the highest possible abstraction, and the convention used is to pre-pend NAF then the class name, then the member function name. The first argument to a member function is the instance of the object.
S->getNumberOfChartsInAtlas()becomesNAFManifoldGetNumberOfChartsInAtlas(S)
S->getRadius()becomesNAFSphereGetRadius(S)
P->getNumberOfCells(0,10)becomesNAFManifoldGetNumberOfCells(P,0,10)

C++ allows polymorphism, Fortran does not. There are member functions and routines in NAO with the same name but different numbers and types of arguments. C++ handles this under the covers by "mangling" the names: changing the name to include the argument types, producing a name that is unique if the number and type of arguments to the routines are different. In the Fortran interface to NAO we have done a mangling by hand, assigning slightly different names to routines with the same name. This is awkward sometimes, but it is necessary.

The Sphere has two constructors:

Obj=new NASphere(); becomes Obj=NAFCreateUnitSphereAtOrigin()
Obj=new NASphere(xC,yC,zC,r) becomes Obj=NAFCreateSphere(xC,yC,zC,r)

Passing NAO objects between routines

Constructors return "integer*4" pointers, and member functions and routines that need to receive NAO objects as input, or produce them as output, do so via these integers. The signature for NAFManifoldGetNumberOfChartsInAtlas(S) is therefore
  integer*4 M
  integer function NAFManifoldGetNumberOfChartsInAtlas(M)

The current outstanding problem is how to deal with lists of NAO objects in the Fortran interface. In the raw interface these are pointer to pointers, but we have not decided yet whether to use a Fortran array or have another integer with a pointer to the list.


[Comments | NAO Home Page]

[Research home page]

[ IBM home page | Order | Privacy | ContactIBM | Legal ]