mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-20 11:40:18 +02:00
* data-rep.texi: Extended to accomodate a full running example,
provided with the manual. * example-smob: A new subdirectory, containing example files for the manual chapter on smobs. * Makefile.am (EXAMPLE_SMOB_FILES, dist-hook): New variable and target, to get the example-smob directory into the distribution. * Makefile.in: Regenerated.
This commit is contained in:
parent
716290a7e0
commit
7d12f03367
3 changed files with 108 additions and 33 deletions
|
@ -1,2 +1,11 @@
|
|||
info_TEXINFOS = data-rep.texi
|
||||
data_rep_TEXINFOS = data-rep.texi version.texi
|
||||
|
||||
EXAMPLE_SMOB_FILES = \
|
||||
ChangeLog Makefile README image-type.c image-type.h myguile.c
|
||||
|
||||
dist-hook:
|
||||
mkdir $(distdir)/example-smob
|
||||
(dest="`cd $(distdir)/example-smob; pwd`"; \
|
||||
cd $(srcdir)/example-smob; \
|
||||
cp $(EXAMPLE_SMOB_FILES) $$dest)
|
||||
|
|
|
@ -89,6 +89,9 @@ qtmds_s = @qtmds_s@
|
|||
|
||||
info_TEXINFOS = data-rep.texi
|
||||
data_rep_TEXINFOS = data-rep.texi version.texi
|
||||
|
||||
EXAMPLE_SMOB_FILES = \
|
||||
ChangeLog Makefile README image-type.c image-type.h myguile.c
|
||||
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
||||
CONFIG_HEADER = ../libguile/scmconfig.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
|
@ -273,6 +276,7 @@ distdir: $(DISTFILES)
|
|||
|| cp -p $$d/$$file $(distdir)/$$file; \
|
||||
done
|
||||
$(MAKE) top_distdir="$(top_distdir)" distdir="$(distdir)" dist-info
|
||||
$(MAKE) top_distdir="$(top_distdir)" distdir="$(distdir)" dist-hook
|
||||
info: $(INFO_DEPS)
|
||||
dvi: $(DVIS)
|
||||
check: all
|
||||
|
@ -330,6 +334,12 @@ mostlyclean-generic distclean-generic clean-generic \
|
|||
maintainer-clean-generic clean mostlyclean distclean maintainer-clean
|
||||
|
||||
|
||||
dist-hook:
|
||||
mkdir $(distdir)/example-smob
|
||||
(dest="`cd $(distdir)/example-smob; pwd`"; \
|
||||
cd $(srcdir)/example-smob; \
|
||||
cp $(EXAMPLE_SMOB_FILES) $$dest)
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
||||
|
|
|
@ -46,7 +46,7 @@ by the Free Software Foundation.
|
|||
@sp 10
|
||||
@comment The title is printed in a large font.
|
||||
@title Data Representation in Guile
|
||||
@subtitle $Id: data-rep.texi,v 1.1 1998-10-07 07:37:16 jimb Exp $
|
||||
@subtitle $Id: data-rep.texi,v 1.2 1998-10-15 21:48:12 jimb Exp $
|
||||
@subtitle For use with Guile @value{VERSION}
|
||||
@author Jim Blandy
|
||||
@author Free Software Foundation
|
||||
|
@ -1090,11 +1090,16 @@ says it comes from ``small object'', referring to the fact that only the
|
|||
@sc{cdr} and part of the @sc{car} of a smob's cell are available for
|
||||
use.} To define a new smob type, the programmer provides Guile with
|
||||
some essential information about the type --- how to print it, how to
|
||||
garbage collect it, @i{et cetera} --- and Guile returns a fresh type tag for
|
||||
garbage collect it, and so on --- and Guile returns a fresh type tag for
|
||||
use in the @sc{car} of new cells. The programmer can then use
|
||||
@code{scm_make_gsubr} to publish a set of C functions to the Scheme
|
||||
world that create and operate on these objects.
|
||||
@code{scm_make_gsubr} to make a set of C functions that create and
|
||||
operate on these objects visible to Scheme code.
|
||||
|
||||
(You can find a complete version of the example code used in this
|
||||
section in the Guile distribution, in @file{doc/example-smob}. That
|
||||
directory includes a makefile and a suitable @code{main} function, so
|
||||
you can build a complete interactive Guile shell, extended with the
|
||||
datatypes described here.)
|
||||
|
||||
@menu
|
||||
* Describing a New Type::
|
||||
|
@ -1167,12 +1172,12 @@ representing eight-bit grayscale images:
|
|||
@example
|
||||
#include <libguile.h>
|
||||
|
||||
long image_tag;
|
||||
|
||||
scm_smobfuns image_funs = @{
|
||||
mark_image, free_image, print_image, 0
|
||||
@};
|
||||
|
||||
long image_tag;
|
||||
|
||||
void
|
||||
init_image_type ()
|
||||
@{
|
||||
|
@ -1251,12 +1256,21 @@ struct image @{
|
|||
@};
|
||||
|
||||
SCM
|
||||
create_image (SCM name, int width, int height)
|
||||
make_image (SCM name, SCM s_width, SCM s_height)
|
||||
@{
|
||||
struct image *image;
|
||||
SCM image_smob;
|
||||
int width, height;
|
||||
|
||||
image = (struct image *) scm_must_malloc (sizeof (*image), "image");
|
||||
SCM_ASSERT (SCM_NIMP (name) && 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");
|
||||
|
@ -1264,8 +1278,8 @@ create_image (SCM name, int width, int height)
|
|||
image->update_func = SCM_BOOL_F;
|
||||
|
||||
SCM_NEWCELL (image_smob);
|
||||
SCM_SETCAR (image_smob, image_tag);
|
||||
SCM_SETCDR (image_smob, image);
|
||||
SCM_SETCAR (image_smob, image_tag);
|
||||
|
||||
return image_smob;
|
||||
@}
|
||||
|
@ -1284,8 +1298,9 @@ non-immediate, whose @sc{car} is the type tag returned by
|
|||
|
||||
For example, here is a simple function that operates on an image smob,
|
||||
and checks the type of its argument. We also present an expanded
|
||||
version of the @code{init_image_type} function, to make clear_image
|
||||
available to the Scheme level.
|
||||
version of the @code{init_image_type} function, to make
|
||||
@code{clear_image} and the image constructor function @code{make_image}
|
||||
visible to Scheme code.
|
||||
@example
|
||||
SCM
|
||||
clear_image (SCM image_smob)
|
||||
|
@ -1313,6 +1328,8 @@ void
|
|||
init_image_type ()
|
||||
@{
|
||||
image_tag = scm_newsmob (&image_funs);
|
||||
|
||||
scm_make_gsubr ("make-image", 3, 0, 0, make_image);
|
||||
scm_make_gsubr ("clear-image", 1, 0, 0, clear_image);
|
||||
@}
|
||||
@end example
|
||||
|
@ -1350,7 +1367,7 @@ function for that smob: the one listed in that smob's
|
|||
@code{scm_smobfuns} structure. It then calls the @code{mark} function,
|
||||
passing it the smob as its only argument.
|
||||
|
||||
The @code{mark} function's is responsible for marking any other Scheme
|
||||
The @code{mark} function is responsible for marking any other Scheme
|
||||
objects the smob refers to. If it does not do so, the objects' mark
|
||||
bits will still be clear when the collector begins to sweep, and the
|
||||
collector will free them. If this occurs, it will probably break, or at
|
||||
|
@ -1469,7 +1486,9 @@ for any unusual activity to interfere with normal code.
|
|||
It is often useful to define very simple smob types --- smobs which have
|
||||
no data to mark, other than the cell itself, or smobs whose @sc{cdr} is
|
||||
simply an ordinary Scheme object, to be marked recursively. Guile
|
||||
provides some functions to handle these common cases.
|
||||
provides some functions to handle these common cases; you can use these
|
||||
functions as your smob type's @code{mark} function, if your smob's
|
||||
structure is simple enough.
|
||||
|
||||
If the smob refers to no other Scheme objects, then no action is
|
||||
necessary; the garbage collector has already marked the smob cell
|
||||
|
@ -1494,13 +1513,21 @@ other than the smob's header cell.
|
|||
|
||||
Here is the complete text of the implementation of the image datatype,
|
||||
as presented in the sections above. We also provide a definition for
|
||||
the smob's @code{print} function.
|
||||
the smob's @code{print} function, and make some objects and functions
|
||||
static, to clarify exactly what the surrounding code is using.
|
||||
|
||||
As mentioned above, you can find this code in the Guile distribution, in
|
||||
@file{doc/example-smob}. That directory includes a makefile and a
|
||||
suitable @code{main} function, so you can build a complete interactive
|
||||
Guile shell, extended with the datatypes described here.)
|
||||
|
||||
@example
|
||||
/* file "image-type.c" */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <libguile.h>
|
||||
|
||||
long image_tag;
|
||||
static long image_tag;
|
||||
|
||||
struct image @{
|
||||
int width, height;
|
||||
|
@ -1515,14 +1542,22 @@ struct image @{
|
|||
SCM update_func;
|
||||
@};
|
||||
|
||||
|
||||
SCM
|
||||
create_image (SCM name, int width, int height)
|
||||
static SCM
|
||||
make_image (SCM name, SCM s_width, SCM s_height)
|
||||
@{
|
||||
struct image *image;
|
||||
SCM image_smob;
|
||||
int width, height;
|
||||
|
||||
image = (struct image *) scm_must_malloc (sizeof (*image), "image");
|
||||
SCM_ASSERT (SCM_NIMP (name) && 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");
|
||||
|
@ -1536,8 +1571,7 @@ create_image (SCM name, int width, int height)
|
|||
return image_smob;
|
||||
@}
|
||||
|
||||
|
||||
SCM
|
||||
static SCM
|
||||
clear_image (SCM image_smob)
|
||||
@{
|
||||
int area;
|
||||
|
@ -1558,8 +1592,7 @@ clear_image (SCM image_smob)
|
|||
return SCM_UNSPECIFIED;
|
||||
@}
|
||||
|
||||
|
||||
SCM
|
||||
static SCM
|
||||
mark_image (SCM image_smob)
|
||||
@{
|
||||
struct image *image = (struct image *) SCM_CDR (image_smob);
|
||||
|
@ -1568,12 +1601,11 @@ mark_image (SCM image_smob)
|
|||
return image->update_func;
|
||||
@}
|
||||
|
||||
|
||||
scm_sizet
|
||||
static scm_sizet
|
||||
free_image (SCM image_smob)
|
||||
@{
|
||||
struct image *image = (struct image *) SCM_CDR (image_smob);
|
||||
scm_sizet size = image->width * image->height + sizeof (*image);
|
||||
scm_sizet size = image->width * image->height + sizeof (struct image);
|
||||
|
||||
free (image->pixels);
|
||||
free (image);
|
||||
|
@ -1581,31 +1613,55 @@ free_image (SCM image_smob)
|
|||
return size;
|
||||
@}
|
||||
|
||||
|
||||
int
|
||||
print_image (SCM obj, SCM port, scm_print_state *pstate)
|
||||
static int
|
||||
print_image (SCM image_smob, SCM port, scm_print_state *pstate)
|
||||
@{
|
||||
struct image *image = (struct image *) SCM_CDR (image_smob);
|
||||
|
||||
scm_gen_puts (scm_regular_string, "#<image ", port);
|
||||
scm_puts ("#<image ", port);
|
||||
scm_display (image->name, port);
|
||||
scm_gen_puts (scm_regular_string, ">", port);
|
||||
scm_puts (">", port);
|
||||
|
||||
/* non-zero means success */
|
||||
return 1;
|
||||
@}
|
||||
|
||||
scm_smobfuns image_funs = @{
|
||||
static scm_smobfuns image_funs = @{
|
||||
mark_image, free_image, print_image, 0
|
||||
@};
|
||||
|
||||
|
||||
void
|
||||
init_image_type ()
|
||||
@{
|
||||
image_tag = scm_newsmob (&image_funs);
|
||||
|
||||
scm_make_gsubr ("clear-image", 1, 0, 0, clear_image);
|
||||
scm_make_gsubr ("make-image", 3, 0, 0, make_image);
|
||||
@}
|
||||
@end example
|
||||
|
||||
Here is a sample build and interaction with the code from the
|
||||
@file{example-smob} directory, on the author's machine:
|
||||
|
||||
@example
|
||||
zwingli:example-smob$ make CC=gcc
|
||||
gcc `guile-config compile` -c image-type.c -o image-type.o
|
||||
gcc `guile-config compile` -c myguile.c -o myguile.o
|
||||
gcc `guile-config link` image-type.o myguile.o -o myguile
|
||||
zwingli:example-smob$ ./myguile
|
||||
guile> make-image
|
||||
#<primitive-procedure make-image>
|
||||
guile> (define i (make-image "Whistler's Mother" 100 100))
|
||||
guile> i
|
||||
#<image Whistler's Mother>
|
||||
guile> (clear-image i)
|
||||
guile> (clear-image 4)
|
||||
ERROR: In procedure clear-image in expression (clear-image 4):
|
||||
ERROR: Wrong type argument in position 1: 4
|
||||
ABORT: (wrong-type-arg)
|
||||
|
||||
Type "(backtrace)" to get more information.
|
||||
guile>
|
||||
@end example
|
||||
|
||||
@bye
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue