
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 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
"NAF". NACreate... routines become NAFCreate...,
S=new NASphere() becomes S=NAFCreateSphere()
P=NACreatePolyhedron("Tetrahedron") becomes P=NAFCreatePolyhedron("Tetrahedron")
NAFDeleteObject().
S->unReference() becomes NAFDeleteObject(S)
P->unReference() becomes NAFDeleteObject(P)
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() becomes NAFManifoldGetNumberOfChartsInAtlas(S)
S->getRadius() becomes NAFSphereGetRadius(S)
P->getNumberOfCells(0,10) becomes NAFManifoldGetNumberOfCells(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)
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.
[ IBM home page | Order | Privacy | ContactIBM | Legal ]