summaryrefslogtreecommitdiff
path: root/doc/ref/libguile-program.texi
diff options
context:
space:
mode:
Diffstat (limited to 'doc/ref/libguile-program.texi')
-rw-r--r--doc/ref/libguile-program.texi151
1 files changed, 78 insertions, 73 deletions
diff --git a/doc/ref/libguile-program.texi b/doc/ref/libguile-program.texi
index f565b916f..3b7408398 100644
--- a/doc/ref/libguile-program.texi
+++ b/doc/ref/libguile-program.texi
@@ -1,6 +1,6 @@
@c -*-texinfo-*-
@c This is part of the GNU Guile Reference Manual.
-@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2005
+@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2005, 2014
@c Free Software Foundation, Inc.
@c See the file guile.texi for copying conditions.
@@ -46,7 +46,7 @@ applications in general.
@menu
* Dia Objective:: Deciding why you want to add Guile.
* Dia Steps:: Four steps required to add Guile.
-* Dia Smobs:: How to represent Dia data in Scheme.
+* Dia Objects:: How to represent Dia data in Scheme.
* Dia Primitives:: Writing Guile primitives for Dia.
* Dia Hook:: Providing a hook for Scheme evaluation.
* Dia Structure:: Overall structure for adding Guile.
@@ -115,8 +115,8 @@ First, you need a way of representing your application-specific objects
--- such as @code{shape} in the previous example --- when they are
passed into the Scheme world. Unless your objects are so simple that
they map naturally into builtin Scheme data types like numbers and
-strings, you will probably want to use Guile's @dfn{SMOB} interface to
-create a new Scheme data type for your objects.
+strings, you will probably want to use Guile's @dfn{foreign object}
+interface to create a new Scheme data type for your objects.
Second, you need to write code for the basic operations like
@code{for-each-shape} and @code{square?} such that they access and
@@ -129,17 +129,18 @@ evaluated.
Finally, you need to restructure your top-level application C code a
little so that it initializes the Guile interpreter correctly and
-declares your @dfn{SMOBs} and @dfn{primitives} to the Scheme world.
+declares your @dfn{foreign objects} and @dfn{primitives} to the Scheme
+world.
The following subsections expand on these four points in turn.
-@node Dia Smobs
+@node Dia Objects
@subsubsection How to Represent Dia Data in Scheme
For all but the most trivial applications, you will probably want to
allow some representation of your domain objects to exist on the Scheme
-level. This is where the idea of SMOBs comes in, and with it issues of
+level. This is where foreign objects come in, and with them issues of
lifetime management and garbage collection.
To get more concrete about this, let's look again at the example we gave
@@ -189,21 +190,21 @@ finished evaluation. How do we avoid this happening?
@end itemize
One resolution of these issues is for the Scheme-level representation of
-a shape to be a new, Scheme-specific C structure wrapped up as a SMOB.
-The SMOB is what is passed into and out of Scheme code, and the
-Scheme-specific C structure inside the SMOB points to Dia's underlying C
-structure so that the code for primitives like @code{square?} can get at
-it.
+a shape to be a new, Scheme-specific C structure wrapped up as a foreign
+object. The foreign object is what is passed into and out of Scheme
+code, and the Scheme-specific C structure inside the foreign object
+points to Dia's underlying C structure so that the code for primitives
+like @code{square?} can get at it.
To cope with an underlying shape being deleted while Scheme code is
still holding onto a Scheme shape value, the underlying C structure
-should have a new field that points to the Scheme-specific SMOB. When a
-shape is deleted, the relevant code chains through to the
-Scheme-specific structure and sets its pointer back to the underlying
-structure to NULL. Thus the SMOB value for the shape continues to
-exist, but any primitive code that tries to use it will detect that the
-underlying shape has been deleted because the underlying structure
-pointer is NULL.
+should have a new field that points to the Scheme-specific foreign
+object. When a shape is deleted, the relevant code chains through to
+the Scheme-specific structure and sets its pointer back to the
+underlying structure to NULL. Thus the foreign object value for the
+shape continues to exist, but any primitive code that tries to use it
+will detect that the underlying shape has been deleted because the
+underlying structure pointer is NULL.
So, to summarize the steps involved in this resolution of the problem
(and assuming that the underlying C structure for a shape is
@@ -238,33 +239,33 @@ struct dia_shape
underlying shape is deleted.
@item
-Wrap @code{struct dia_guile_shape} as a SMOB type.
+Wrap @code{struct dia_guile_shape} as a foreign object type.
@item
Whenever you need to represent a C shape onto the Scheme level, create a
-SMOB instance for it, and pass that.
+foreign object instance for it, and pass that.
@item
-In primitive code that receives a shape SMOB instance, check the
+In primitive code that receives a shape foreign object instance, check the
@code{c_shape} field when decoding it, to find out whether the
underlying C shape is still there.
@end itemize
-As far as memory management is concerned, the SMOB values and their
-Scheme-specific structures are under the control of the garbage
+As far as memory management is concerned, the foreign object values and
+their Scheme-specific structures are under the control of the garbage
collector, whereas the underlying C structures are explicitly managed in
exactly the same way that Dia managed them before we thought of adding
Guile.
-When the garbage collector decides to free a shape SMOB value, it calls
-the @dfn{SMOB free} function that was specified when defining the shape
-SMOB type. To maintain the correctness of the @code{guile_shape} field
-in the underlying C structure, this function should chain through to the
-underlying C structure (if it still exists) and set its
-@code{guile_shape} field to NULL.
+When the garbage collector decides to free a shape foreign object value,
+it calls the @dfn{finalizer} function that was specified when defining
+the shape foreign object type. To maintain the correctness of the
+@code{guile_shape} field in the underlying C structure, this function
+should chain through to the underlying C structure (if it still exists)
+and set its @code{guile_shape} field to NULL.
-For full documentation on defining and using SMOB types, see
-@ref{Defining New Types (Smobs)}.
+For full documentation on defining and using foreign object types, see
+@ref{Defining New Foreign Object Types}.
@node Dia Primitives
@@ -283,11 +284,11 @@ static SCM square_p (SCM shape)
@{
struct dia_guile_shape * guile_shape;
- /* Check that arg is really a shape SMOB. */
- scm_assert_smob_type (shape_tag, shape);
+ /* Check that arg is really a shape object. */
+ scm_assert_foreign_object_type (shape_type, shape);
/* Access Scheme-specific shape structure. */
- guile_shape = SCM_SMOB_DATA (shape);
+ guile_shape = scm_foreign_object_ref (shape, 0);
/* Find out if underlying shape exists and is a
square; return answer as a Scheme boolean. */
@@ -297,26 +298,28 @@ static SCM square_p (SCM shape)
@end lisp
Notice how easy it is to chain through from the @code{SCM shape}
-parameter that @code{square_p} receives --- which is a SMOB --- to the
-Scheme-specific structure inside the SMOB, and thence to the underlying
-C structure for the shape.
-
-In this code, @code{scm_assert_smob_type}, @code{SCM_SMOB_DATA}, and
-@code{scm_from_bool} are from the standard Guile API. We assume that
-@code{shape_tag} was given to us when we made the shape SMOB type, using
-@code{scm_make_smob_type}. The call to @code{scm_assert_smob_type}
-ensures that @var{shape} is indeed a shape. This is needed to guard
-against Scheme code using the @code{square?} procedure incorrectly, as
-in @code{(square? "hello")}; Scheme's latent typing means that usage
-errors like this must be caught at run time.
+parameter that @code{square_p} receives --- which is a foreign object
+--- to the Scheme-specific structure inside the foreign object, and
+thence to the underlying C structure for the shape.
+
+In this code, @code{scm_assert_foreign_object_type},
+@code{scm_foreign_object_ref}, and @code{scm_from_bool} are from the
+standard Guile API. We assume that @code{shape_type} was given to us
+when we made the shape foreign object type, using
+@code{scm_make_foreign_object_type}. The call to
+@code{scm_assert_foreign_object_type} ensures that @var{shape} is indeed
+a shape. This is needed to guard against Scheme code using the
+@code{square?} procedure incorrectly, as in @code{(square? "hello")};
+Scheme's latent typing means that usage errors like this must be caught
+at run time.
Having written the C code for your primitives, you need to make them
available as Scheme procedures by calling the @code{scm_c_define_gsubr}
-function. @code{scm_c_define_gsubr} (@pxref{Primitive Procedures}) takes arguments that
-specify the Scheme-level name for the primitive and how many required,
-optional and rest arguments it can accept. The @code{square?} primitive
-always requires exactly one argument, so the call to make it available
-in Scheme reads like this:
+function. @code{scm_c_define_gsubr} (@pxref{Primitive Procedures})
+takes arguments that specify the Scheme-level name for the primitive and
+how many required, optional and rest arguments it can accept. The
+@code{square?} primitive always requires exactly one argument, so the
+call to make it available in Scheme reads like this:
@lisp
scm_c_define_gsubr ("square?", 1, 0, 0, square_p);
@@ -384,7 +387,7 @@ do lots of initialization and setup stuff
@itemize @bullet
@item
-define all SMOB types
+define all foreign object types
@item
export primitives to Scheme using @code{scm_c_define_gsubr}
@item
@@ -397,13 +400,13 @@ In other words, you move the guts of what was previously in your
then add a @code{scm_boot_guile} call, with @code{inner_main} as a
parameter, to the end of @code{main}.
-Assuming that you are using SMOBs and have written primitive code as
-described in the preceding subsections, you also need to insert calls to
-declare your new SMOBs and export the primitives to Scheme. These
-declarations must happen @emph{inside} the dynamic scope of the
-@code{scm_boot_guile} call, but also @emph{before} any code is run that
-could possibly use them --- the beginning of @code{inner_main} is an
-ideal place for this.
+Assuming that you are using foreign objects and have written primitive
+code as described in the preceding subsections, you also need to insert
+calls to declare your new foreign objects and export the primitives to
+Scheme. These declarations must happen @emph{inside} the dynamic scope
+of the @code{scm_boot_guile} call, but also @emph{before} any code is
+run that could possibly use them --- the beginning of @code{inner_main}
+is an ideal place for this.
@node Dia Advanced
@@ -425,7 +428,8 @@ move the code that lays out and displays Dia objects from C to Scheme.
As you follow this path, it naturally becomes less useful to maintain a
distinction between Dia's original non-Guile-related source code, and
-its later code implementing SMOBs and primitives for the Scheme world.
+its later code implementing foreign objects and primitives for the
+Scheme world.
For example, suppose that the original source code had a
@code{dia_change_fill_pattern} function:
@@ -440,8 +444,8 @@ void dia_change_fill_pattern (struct dia_shape * shape,
During initial Guile integration, you add a @code{change_fill_pattern}
primitive for Scheme purposes, which accesses the underlying structures
-from its SMOB values and uses @code{dia_change_fill_pattern} to do the
-real work:
+from its foreign object values and uses @code{dia_change_fill_pattern}
+to do the real work:
@lisp
SCM change_fill_pattern (SCM shape, SCM pattern)
@@ -487,22 +491,23 @@ So further Guile integration progressively @emph{reduces} the amount of
functional C code that you have to maintain over the long term.
A similar argument applies to data representation. In the discussion of
-SMOBs earlier, issues arose because of the different memory management
-and lifetime models that normally apply to data structures in C and in
-Scheme. However, with further Guile integration, you can resolve this
-issue in a more radical way by allowing all your data structures to be
-under the control of the garbage collector, and kept alive by references
-from the Scheme world. Instead of maintaining an array or linked list
-of shapes in C, you would instead maintain a list in Scheme.
+foreign objects earlier, issues arose because of the different memory
+management and lifetime models that normally apply to data structures in
+C and in Scheme. However, with further Guile integration, you can
+resolve this issue in a more radical way by allowing all your data
+structures to be under the control of the garbage collector, and kept
+alive by references from the Scheme world. Instead of maintaining an
+array or linked list of shapes in C, you would instead maintain a list
+in Scheme.
Rather like the coalescing of @code{dia_change_fill_pattern} and
@code{change_fill_pattern}, the practical upshot of such a change is
that you would no longer have to keep the @code{dia_shape} and
@code{dia_guile_shape} structures separate, and so wouldn't need to
worry about the pointers between them. Instead, you could change the
-SMOB definition to wrap the @code{dia_shape} structure directly, and
-send @code{dia_guile_shape} off to the scrap yard. Cut out the middle
-man!
+foreign object definition to wrap the @code{dia_shape} structure
+directly, and send @code{dia_guile_shape} off to the scrap yard. Cut
+out the middle man!
Finally, we come to the holy grail of Guile's free software / extension
language approach. Once you have a Scheme representation for