Warning: This is the manual of the legacy Guile 2.0 series. You may want to read the manual of the current stable series instead.
Next: Type checking, Previous: Describing a New Type, Up: Defining New Types (Smobs) [Contents][Index]
Normally, smobs can have one immediate word of data. This word
stores either a pointer to an additional memory block that holds the
real data, or it might hold the data itself when it fits. The word is
large enough for a SCM
value, a pointer to void
, or an
integer that fits into a size_t
or ssize_t
.
You can also create smobs that have two or three immediate words, and when these words suffice to store all data, it is more efficient to use these super-sized smobs instead of using a normal smob plus a memory block. See Double Smobs, for their discussion.
Guile provides functions for managing memory which are often helpful when implementing smobs. See Memory Blocks.
To retrieve the immediate word of a smob, you use the macro
SCM_SMOB_DATA
. It can be set with SCM_SET_SMOB_DATA
.
The 16 extra bits can be accessed with SCM_SMOB_FLAGS
and
SCM_SET_SMOB_FLAGS
.
The two macros SCM_SMOB_DATA
and SCM_SET_SMOB_DATA
treat
the immediate word as if it were of type scm_t_bits
, which is
an unsigned integer type large enough to hold a pointer to
void
. Thus you can use these macros to store arbitrary
pointers in the smob word.
When you want to store a SCM
value directly in the immediate
word of a smob, you should use the macros SCM_SMOB_OBJECT
and
SCM_SET_SMOB_OBJECT
to access it.
Creating a smob instance can be tricky when it consists of multiple steps that allocate resources. Most of the time, this is mainly about allocating memory to hold associated data structures. Using memory managed by the garbage collector simplifies things: the garbage collector will automatically scan those data structures for pointers, and reclaim them when they are no longer referenced.
Continuing the example from above, if the global variable
image_tag
contains a tag returned by scm_make_smob_type
,
here is how we could construct a smob whose immediate word contains a
pointer to a freshly allocated struct image
:
SCM make_image (SCM name, SCM s_width, SCM s_height) { SCM smob; struct image *image; int width = scm_to_int (s_width); int height = scm_to_int (s_height); /* Step 1: Allocate the memory block. */ image = (struct image *) scm_gc_malloc (sizeof (struct image), "image"); /* Step 2: Initialize it with straight code. */ image->width = width; image->height = height; image->pixels = NULL; image->name = SCM_BOOL_F; image->update_func = SCM_BOOL_F; /* Step 3: Create the smob. */ smob = scm_new_smob (image_tag, image); /* Step 4: Finish the initialization. */ image->name = name; image->pixels = scm_gc_malloc_pointerless (width * height, "image pixels"); return smob; }
We use scm_gc_malloc_pointerless
for the pixel buffer to tell the
garbage collector not to scan it for pointers. Calls to
scm_gc_malloc
, scm_new_smob
, and
scm_gc_malloc_pointerless
raise an exception in out-of-memory
conditions; the garbage collector is able to reclaim previously
allocated memory if that happens.
Next: Type checking, Previous: Describing a New Type, Up: Defining New Types (Smobs) [Contents][Index]