Next: Reporting Bugs, Previous: Defining New Wrapped Types, Up: A More Detailed Example [Contents][Index]
aggregated
Type QualifierThe 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-function
s (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: Reporting Bugs, Previous: Defining New Wrapped Types, Up: A More Detailed Example [Contents][Index]