Previous | Table of Contents | Next |
It is often useful to augment Scheme with data types specific to the application, allowing the interpreted code to refer to resources and data structures used by the application. For example, the window values in SCWM are pointers to SCWMs internal window structures, wrapped with enough typing information to keep the interpreter consistent. Scheme functions such as full-height can manipulate them, and SCWM primitive functions such as lower-window can easily extract the underlying data structure.
Smobs are Guiles mechanism for adding new types. (Smob is an abbreviation of small object.) The full procedure for defining new smobs is rather involved, so I only sketch it here. Guiles manual describes the process fully, and examples abound in Guile-based packages such as SCWM and in the Guile source code itself.
To implement a new smob type, the user must first write a set of C functions that Guile may call to perform certain essential housekeeping tasks on instances of the type:
For example, here is SCWMs free_font function, called by the garbage collector to destroy unreferenced font objects:
size_t free_font(SCM obj) { /* OBJ is the font smob to free. Extract the XFont object and the font name, free them, and then free the SCWM font object itself. */ XFreeFont(dpy, XFONT(obj)); free(FONTNAME(obj)); free(FONT(obj)); return (0); }
Given the set of housekeeping functions described here, the programmer must initialize a scm_smobfuns structure to point to them. For example, here is SCWMs declaration of the scm_smobfuns structure for the font data type:
static scm_smobfuns font_smobfuns = { &scm_mark0, &free_font, &print_font, 0 };
Because fonts are relatively simple objects, the font_smobfuns structure cites a standard Guile function, scm_mark0, to mark fonts for the garbage collector. The structure lists the free_font function to be called when a font object dies.
Given the initialized scm_smobfuns structure, the application calls scm_newsmob to register the font smob type with Guile, along with several other new types:
void init_scwm_types(void) { scm_tc16_scwm_font = scm_newsmob(&font_smobfuns); scm_tc16_scwm_color = scm_newsmob(&color_smobfuns); scm_tc16_scwm_window = scm_newsmob(&window_smobfuns); scm_tc16_scwm_menu = scm_newsmob(&menu_smobfuns); }
When the application creates a new instance of a smob type, it must tag the instance with the value returned by scm_newsmob; this allows Guile, given a smob, to find the functions to manage it. For example, here is how SCWM allocates a new font object:
SCM load_font(SCM fname) { /* Allocate storage for our font structure. */ font = (scwm_font *)safemalloc(sizeof(*font)); /* Create a new Scheme object, tagged as a font smob, and pointing to the storage we have allocated. Notice that scm_tc16_scwm_font is the tag returned by scm_newsmob. */ SCM_NEWCELL(answer); SCM_SETCAR(answer, scm_tc16_scwm_font); SCM_SETCDR(answer, (SCM) font); /* Initialize our font structure. */ XFONT(answer) = xfs; FONTNAME(answer) = fn; return answer; }
Previous | Table of Contents | Next |