Node:Creating Instances, Next:Type checking, Previous:Describing a New Type, Up:Defining New Types (Smobs)
Like other non-immediate types, smobs start with a cell whose first word contains typing information, and whose remaining words are free for any use.
After the header word containing the type code, smobs can have either
one, two or three additional words of data. These words store either a
pointer to the internal C structure holding the smob-specific data, or
the smob data itself. To create an instance of a smob type following
these standards, you should use SCM_NEWSMOB
, SCM_NEWSMOB2
or SCM_NEWSMOB3
:1
void SCM_NEWSMOB(SCM value, scm_t_bits tag, void *data) | Macro |
void SCM_NEWSMOB2(SCM value, scm_t_bits tag, void *data1, void *data2) | Macro |
void SCM_NEWSMOB3(SCM value, scm_t_bits tag, void *data1, void *data2, void *data3) | Macro |
Make value contain a smob instance of the type with tag tag
and smob data data (or data1, data2, and data3).
value must be previously declared as C type SCM .
|
Since it is often the case (e.g., in smob constructors) that you will create a smob instance and return it, there is also a slightly specialized macro for this situation:
fn_returns SCM_RETURN_NEWSMOB(scm_t_bits tag, void *data) | Macro |
fn_returns SCM_RETURN_NEWSMOB2(scm_t_bits tag, void *data1, void *data2) | Macro |
fn_returns SCM_RETURN_NEWSMOB3(scm_t_bits tag, void *data1, void *data2, void *data3) | Macro |
This macro expands to a block of code that creates a smob instance of
the type with tag tag and smob data data (or data1,
data2, and data3), and causes the surrounding function to
return that SCM value. It should be the last piece of code in
a block.
|
Guile provides the following functions for managing memory, which are often helpful when implementing smobs:
char * scm_must_malloc (size_t len, char *what) | Function |
Allocate len bytes of memory, using malloc , and return a
pointer to them.
If there is not enough memory available, invoke the garbage collector, and try once more. If there is still not enough, signal an error, reporting that we could not allocate what. This function also helps maintain statistics about the size of the heap. |
char * scm_must_realloc (char *addr, size_t olen, size_t len, char *what) | Function |
Resize (and possibly relocate) the block of memory at addr, to
have a size of len bytes, by calling realloc . Return a
pointer to the new block.
If there is not enough memory available, invoke the garbage collector, and try once more. If there is still not enough, signal an error, reporting that we could not allocate what. The value olen should be the old size of the block of memory at addr; it is only used for keeping statistics on the size of the heap. |
void scm_must_free (char *addr) | Function |
Free the block of memory at addr, using free . If
addr is zero, signal an error, complaining of an attempt to free
something that is already free.
This does no record-keeping; instead, the smob's This function isn't usually sufficiently different from the usual
|
Continuing the above example, if the global variable image_tag
contains a tag returned by scm_make_smob_type
, here is how we
could construct a smob whose CDR contains a pointer to a freshly
allocated struct image
:
struct image { int width, height; char *pixels; /* The name of this image */ SCM name; /* A function to call when this image is modified, e.g., to update the screen, or SCM_BOOL_F if no action necessary */ SCM update_func; }; SCM make_image (SCM name, SCM s_width, SCM s_height) { struct image *image; int width, height; SCM_ASSERT (SCM_STRINGP (name), name, SCM_ARG1, "make-image"); SCM_ASSERT (SCM_INUMP (s_width), s_width, SCM_ARG2, "make-image"); SCM_ASSERT (SCM_INUMP (s_height), s_height, SCM_ARG3, "make-image"); width = SCM_INUM (s_width); height = SCM_INUM (s_height); image = (struct image *) scm_must_malloc (sizeof (struct image), "image"); image->width = width; image->height = height; image->pixels = scm_must_malloc (width * height, "image pixels"); image->name = name; image->update_func = SCM_BOOL_F; SCM_RETURN_NEWSMOB (image_tag, image); }
The SCM_NEWSMOB2
and
SCM_NEWSMOB3
variants will allocate double cells and thus use
twice as much memory as smobs created by SCM_NEWSMOB
.