Node:Describing a New Type, Next:, Up:Defining New Types (Smobs)



18.3.1 Describing a New Type

To define a new type, the programmer must write four functions to manage instances of the type:

mark
Guile will apply this function to each instance of the new type it encounters during garbage collection. This function is responsible for telling the collector about any other non-immediate objects the object refers to. The default smob mark function is to not mark any data. See Garbage Collecting Smobs, for more details.
free
Guile will apply this function to each instance of the new type it could not find any live pointers to. The function should release all resources held by the object and return the number of bytes released. This is analogous to the Java finalization method- it is invoked at an unspecified time (when garbage collection occurs) after the object is dead. The default free function frees the smob data (if the size of the struct passed to scm_make_smob_type is non-zero) using scm_must_free and returns the size of that struct. See Garbage Collecting Smobs, for more details.
print
Guile will apply this function to each instance of the new type to print the value, as for display or write. The function should write a printed representation of exp on port, in accordance with the parameters in pstate. (For more information on print states, see Port Data.) The default print function prints #<NAME ADDRESS> where NAME is the first argument passed to scm_make_smob_type.
equalp
If Scheme code asks the equal? function to compare two instances of the same smob type, Guile calls this function. It should return SCM_BOOL_T if a and b should be considered equal?, or SCM_BOOL_F otherwise. If equalp is NULL, equal? will assume that two instances of this type are never equal? unless they are eq?.

To actually register the new smob type, call scm_make_smob_type:

scm_t_bits scm_make_smob_type (const char *name, size_t size) Function
This function implements the standard way of adding a new smob type, named name, with instance size size, to the system. The return value is a tag that is used in creating instances of the type. If size is 0, then no memory will be allocated when instances of the smob are created, and nothing will be freed by the default free function. Default values are provided for mark, free, print, and, equalp, as described above. If you want to customize any of these functions, the call to scm_make_smob_type should be immediately followed by calls to one or several of scm_set_smob_mark, scm_set_smob_free, scm_set_smob_print, and/or scm_set_smob_equalp.

Each of the below scm_set_smob_XXX functions registers a smob special function for a given type. Each function is intended to be used only zero or one time per type, and the call should be placed immediately following the call to scm_make_smob_type.

void scm_set_smob_mark (scm_t_bits tc, SCM (*mark) (SCM)) Function
This function sets the smob marking procedure for the smob type specified by the tag tc. tc is the tag returned by scm_make_smob_type.

void scm_set_smob_free (scm_t_bits tc, size_t (*free) (SCM)) Function
This function sets the smob freeing procedure for the smob type specified by the tag tc. tc is the tag returned by scm_make_smob_type.

void scm_set_smob_print (scm_t_bits tc, int (*print) (SCM, SCM, scm_print_state*)) Function
This function sets the smob printing procedure for the smob type specified by the tag tc. tc is the tag returned by scm_make_smob_type.

void scm_set_smob_equalp (scm_t_bits tc, SCM (*equalp) (SCM, SCM)) Function
This function sets the smob equality-testing predicate for the smob type specified by the tag tc. tc is the tag returned by scm_make_smob_type.

In versions 1.4 and earlier, there was another way of creating smob types, using scm_make_smob_type_mfpe. This function is now deprecated and will be removed in a future version of Guile. You should use the mechanism described above for new code, and change old code not to use deprecated features.

Instead of using scm_make_smob_type and calling each of the individual scm_set_smob_XXX functions to register each special function independently, you could use scm_make_smob_type_mfpe to register all of the special functions at once as you create the smob type

long scm_make_smob_type_mfpe(const char *name, size_t size, SCM (*mark) (SCM), size_t (*free) (SCM), int (*print) (SCM, SCM, scm_print_state*), SCM (*equalp) (SCM, SCM)) Function
This function invokes scm_make_smob_type on its first two arguments to add a new smob type named name, with instance size size to the system. It also registers the mark, free, print, equalp smob special functions for that new type. Any of these parameters can be NULL to have that special function use the default behavior for guile. The return value is a tag that is used in creating instances of the type. If size is 0, then no memory will be allocated when instances of the smob are created, and nothing will be freed by the default free function.

For example, here is how one might declare and register a new type representing eight-bit gray-scale images:

#include <libguile.h>

static scm_t_bits image_tag;

void
init_image_type (void)
{
  image_tag = scm_make_smob_type ("image", sizeof (struct image));
  scm_set_smob_mark (image_tag, mark_image);
  scm_set_smob_free (image_tag, free_image);
  scm_set_smob_print (image_tag, print_image);
}