Next: , Previous: , Up: A More Detailed Example   [Contents][Index]


2.3 The aggregated Type Qualifier

The aggregated type qualifier is mostly useful when wrapping C functions (constructors) that return a new object which aggregates objects passed as its input parameters. In order to illustrate the need for this typespec, let’s imagine the following C API:

/* Return a new stuff.  */
stuff_t *make_stuff (void);

/* Return a stuff container that contains a pointer to CONTAINED.
   Note that the container returned is _not_ responsible for
   deallocating the resources attached to CONTAINED.  */
stuff_container_t *make_stuff_container (stuff_t *contained);

And now, imagine the following Scheme code that uses bindings of the above functions:

(define c (make-stuff-container (make-stuff)))

Suppose the two C types are wrapped as WCTs (see Wrapping a C Pointer Type). The call to make-stuff will create a new Scheme object (a WCP, or a “SMOB” in Guile terms, see SMOBs in The GNU Guile Reference Manual) for the underlying C object. However, as soon as make-stuff-container has returned, the Scheme code no longer holds any SMOB representing the value that was returned by make-stuff. Consequently, the SMOB returned by make-stuff may soon be garbage-collected by Guile, and its underlying C object (originally returned by make_stuff ()) may soon get freed as well.

But, here is the problem: the C stuff_container_t object still contains a pointer to that stuff_t object that has just been deleted! The goal of the aggregated typespec is to solve situations like this one. In the example above, the wrapped function and the container type should be specified as follows:

(wrap-as-wct! ws
              #:name '<stuff>
              #:c-type-name "stuff_t *"
              #:c-const-type-name "const stuff_t *"
              #:allowed-options '(aggregated))

...

(wrap-function! ws
                #:name 'make-stuff-container
                #:c-name "make_stuff_container"
                #:returns '<stuff-container>
                #:arguments '(((<stuff> aggregated) stuff)))

Literally, this means: “the argument stuff of make-stuff-container is aggregated by the object returned by make-stuff-container; therefore, it may not be GC’d unless the object returned by make-stuff-container is GC’d too.”

Additionally, G-Wrap, in this case, enforces the finalization order of WCPs: even if both the referrer (the <stuff-container> object) and its dependency (the stuff argument) become unreachable during the same GC phase, G-Wrap makes sure that their wcp-free-functions (see Wrapping a C Pointer Type) are called in the right order, i.e., referrer first, dependency second.

Note that some libraries, such as GTK+, solve this problem by relying on reference counting: aggregating objects must increment the reference counter of the objects they refer to. The aggregated type qualifier facility can be seen as a solution for those C libraries that do not use reference counting but have memory ownership semantics similar to the ones described above. An example of such a library is Berkeley DB.


Next: , Previous: , Up: A More Detailed Example   [Contents][Index]