Any variables declared in the implementation source file will, by virtue of Babel's encapsulation, be private. The data can be global to the class -- as in static variables declared within the _includes splicer block at the top of the class's _Impl.c file -- or local to an instance -- as in variables declared through the private data structure automatically generated in the class's _Impl.h file. In the former case, special initialization procedures can be added to the built-in _load() method that is guaranteed to be called exactly once per class -- before any user-defined methods can even be invoked. The latter case relies on the class-specific data structure automatically generated in the implementation's header file. As illustrated in the foo.bar example below, the implementor is free to define suitable contents.
/* * Private data for class foo.bar */ struct foo_bar__data { /* DO-NOT-DELETE splicer.begin(foo.bar._data) */ int d_my_int_array[MY_MAX_ARRAY_SIZE]; double d_my_double; /* DO-NOT-DELETE splicer.end(foo.bar._data) */ }
Upon instantiation, the object's data structure is automatically
initialized to NULL before the built-in _ctor() method
is invoked. Initialization of private data first requires sufficient
memory be allocated, as follows
void impl_foo_bar__ctor( /* in */ foo_bar self) { /* DO-NOT-DELETE splicer.begin(foo.bar._ctor) */ int i; struct foo_bar__data *dataPtr = malloc(sizeof(struct foo_bar__data)); TSTT_Triangle_Mesh__set_data(self, dataPtr); if (dataPtr) { for (i=0; i<MY_MAX_ARRAY_SIZE; i++) { dataPtr->d_my_int_array[i] = i; } dataPtr->d_my_double = 0.0; } /* DO-NOT-DELETE splicer.end(foo.bar._ctor) */ }
To avoid leaking memory, allocated private data must be released during
instance destruction. This is accomplished through the built-in
_dtor() method. Continuing with the foo.bar example, the
memory is freed as follows
void impl_foo_bar__dtor( /* in */ foo_bar self) { /* DO-NOT-DELETE splicer.begin(foo.bar._dtor) */ struct foo_bar__data *dataPtr = foo_bar__get_data(self); if (dataPtr) { memset(dataPtr, 0, sizeof(struct foo_bar__data)); free((void*)dataPtr); } foo_bar__set_data(self, NULL); /* DO-NOT-DELETE splicer.end(foo.bar._dtor) */ }
Notice all memory locations are initialized to zero before being freed and the internal data pointer set to NULL. These practices are recommended.
Hence, Babel supports the declaration and maintenance of private data on class and instance basis.