Any variables declared in the implementation source file will, by virtue of Babel's encapsulation, be private. Special initialization procedures can be added to the built-in _load() method that is guaranteed to be called exactly once per class to set global class data -- before any user-defined methods can even be invoked. Alternatively, if private data (sometimes referred to as state) needs to be added to a FORTRAN 77 class, SIDL arrays can be used to store the data. This is certainly not the only way to implement a FORTRAN 77 class with state, but it's one that will work wherever Babel works.
The SIDL IOR keeps a pointer (i.e., a C void *) for each object in order to support private data. Like their C equivalents, each FORTRAN 77 skeleton provides two functions for accessing the private pointer. Although the pointer arguments to the methods are 64-bit integers in FORTRAN 77, the number of bits actually stored by the IOR is determined by sizeof(void *). Babel/SIDL does not provide a low level mechanism for FORTRAN 77 to allocate memory to use for the private data pointer.
The following example illustrates the process of managing private data
using the automatically generated constructor subroutine, _ctor
subroutine example_withState__ctor_fi(self, exception) implicit none integer*8 self, exception C DO-NOT-DELETE splicer.begin(example.withState._ctor) integer*8 statearray, logarray, dblarray call sidl_opaque__array_create1d_f(2, statearray) call sidl_bool__array_create1d_f(3, logarray) call sidl_double__array_create1d_f(2, dblarray) if ((statearray .ne. 0) .and. (logarray .ne. 0) .and. $ (dblarray .ne. 0)) then call sidl_opaque__array_set1_f(statearray, 0, logarray) call sidl_opaque__array_set1_f(statearray, 1, dblarray) else C a real implementation would not leak memory like this one statearray = 0 endif call example_withState__set_data_f(self, statearray) C DO-NOT-DELETE splicer.end(example.withState._ctor) end
Of course, it is up to the implementation to associate
elements of the arrays with particular state variables. For example,
element 0 of the double array could be the kinematic
viscosity and element 1 the airspeed velocity of an unladen
swallow. Element 0 of the boolean array could specify
African (true) or
European (false). The destructor implementation for this class could look
something like
subroutine example_withState__dtor_fi(self, exception) implicit none integer*8 self, exception C DO-NOT-DELETE splicer.begin(example.withState._dtor) integer*8 statearray, logarray, dblarray call example_withState__get_data_f(self, statearray) if (statearray .ne. 0) then call sidl_opaque__array_get1_f(statearray, 0, logarray) call sidl_opaque__array_get1_f(statearray, 1, dblarray) call sidl_bool__array_deleteRef_f(logarray) call sidl_double__array_deleteRef_f(dblarray) call sidl_opaque__array_deleteRef_f(statearray) C the following two lines are not strictly necessary statearray = 0 call example_withState__set_data_f(self, statearray) endif C DO-NOT-DELETE splicer.end(example.withState._dtor) end
Continuing with this example, an accessor function for the airspeed velocity
of an unladen swallow could be implemented as follows
subroutine example_withState_getAirspeedVelocity_fi( $ self, velocity, exception) implicit none integer*8 self, exception real*8 velocity C DO-NOT-DELETE splicer.begin(example.withState.getAirspeedVelocity) integer*8 statearray, dblarray call example_withState__get_data_f(self, statearray) if (statearray .ne. 0) then call sidl_opaque__array_get1_f(statearray, 1, dblarray) call sidl_double__array_get1_f(dblarray, 1, velocity) endif C DO-NOT-DELETE splicer.end(example.withState.getAirspeedVelocity) end