libguile-smobs.texi 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700
  1. @c -*-texinfo-*-
  2. @c This is part of the GNU Guile Reference Manual.
  3. @c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2005
  4. @c Free Software Foundation, Inc.
  5. @c See the file guile.texi for copying conditions.
  6. @node Defining New Types (Smobs)
  7. @section Defining New Types (Smobs)
  8. @dfn{Smobs} are Guile's mechanism for adding new primitive types to
  9. the system. The term ``smob'' was coined by Aubrey Jaffer, who says
  10. it comes from ``small object'', referring to the fact that they are
  11. quite limited in size: they can hold just one pointer to a larger
  12. memory block plus 16 extra bits.
  13. To define a new smob type, the programmer provides Guile with some
  14. essential information about the type --- how to print it, how to
  15. garbage collect it, and so on --- and Guile allocates a fresh type tag
  16. for it. The programmer can then use @code{scm_c_define_gsubr} to make
  17. a set of C functions visible to Scheme code that create and operate on
  18. these objects.
  19. (You can find a complete version of the example code used in this
  20. section in the Guile distribution, in @file{doc/example-smob}. That
  21. directory includes a makefile and a suitable @code{main} function, so
  22. you can build a complete interactive Guile shell, extended with the
  23. datatypes described here.)
  24. @menu
  25. * Describing a New Type::
  26. * Creating Instances::
  27. * Type checking::
  28. * Garbage Collecting Smobs::
  29. * Garbage Collecting Simple Smobs::
  30. * Remembering During Operations::
  31. * Double Smobs::
  32. * The Complete Example::
  33. @end menu
  34. @node Describing a New Type
  35. @subsection Describing a New Type
  36. To define a new type, the programmer must write four functions to
  37. manage instances of the type:
  38. @table @code
  39. @item mark
  40. Guile will apply this function to each instance of the new type it
  41. encounters during garbage collection. This function is responsible for
  42. telling the collector about any other @code{SCM} values that the object
  43. has stored. The default smob mark function does nothing.
  44. @xref{Garbage Collecting Smobs}, for more details.
  45. @item free
  46. Guile will apply this function to each instance of the new type that is
  47. to be deallocated. The function should release all resources held by
  48. the object. This is analogous to the Java finalization method-- it is
  49. invoked at an unspecified time (when garbage collection occurs) after
  50. the object is dead. The default free function frees the smob data (if
  51. the size of the struct passed to @code{scm_make_smob_type} is non-zero)
  52. using @code{scm_gc_free}. @xref{Garbage Collecting Smobs}, for more
  53. details.
  54. This function operates while the heap is in an inconsistent state and
  55. must therefore be careful. @xref{Smobs}, for details about what this
  56. function is allowed to do.
  57. @item print
  58. Guile will apply this function to each instance of the new type to print
  59. the value, as for @code{display} or @code{write}. The default print
  60. function prints @code{#<NAME ADDRESS>} where @code{NAME} is the first
  61. argument passed to @code{scm_make_smob_type}. For more information on
  62. printing, see @ref{Port Data}.
  63. @item equalp
  64. If Scheme code asks the @code{equal?} function to compare two instances
  65. of the same smob type, Guile calls this function. It should return
  66. @code{SCM_BOOL_T} if @var{a} and @var{b} should be considered
  67. @code{equal?}, or @code{SCM_BOOL_F} otherwise. If @code{equalp} is
  68. @code{NULL}, @code{equal?} will assume that two instances of this type are
  69. never @code{equal?} unless they are @code{eq?}.
  70. @end table
  71. To actually register the new smob type, call @code{scm_make_smob_type}.
  72. It returns a value of type @code{scm_t_bits} which identifies the new
  73. smob type.
  74. The four special functions described above are registered by calling
  75. one of @code{scm_set_smob_mark}, @code{scm_set_smob_free},
  76. @code{scm_set_smob_print}, or @code{scm_set_smob_equalp}, as
  77. appropriate. Each function is intended to be used at most once per
  78. type, and the call should be placed immediately following the call to
  79. @code{scm_make_smob_type}.
  80. There can only be at most 256 different smob types in the system.
  81. Instead of registering a huge number of smob types (for example, one
  82. for each relevant C struct in your application), it is sometimes
  83. better to register just one and implement a second layer of type
  84. dispatching on top of it. This second layer might use the 16 extra
  85. bits to extend its type, for example.
  86. Here is how one might declare and register a new type representing
  87. eight-bit gray-scale images:
  88. @example
  89. #include <libguile.h>
  90. struct image @{
  91. int width, height;
  92. char *pixels;
  93. /* The name of this image */
  94. SCM name;
  95. /* A function to call when this image is
  96. modified, e.g., to update the screen,
  97. or SCM_BOOL_F if no action necessary */
  98. SCM update_func;
  99. @};
  100. static scm_t_bits image_tag;
  101. void
  102. init_image_type (void)
  103. @{
  104. image_tag = scm_make_smob_type ("image", sizeof (struct image));
  105. scm_set_smob_mark (image_tag, mark_image);
  106. scm_set_smob_free (image_tag, free_image);
  107. scm_set_smob_print (image_tag, print_image);
  108. @}
  109. @end example
  110. @node Creating Instances
  111. @subsection Creating Instances
  112. Normally, smobs can have one @emph{immediate} word of data. This word
  113. stores either a pointer to an additional memory block that holds the
  114. real data, or it might hold the data itself when it fits. The word is
  115. large enough for a @code{SCM} value, a pointer to @code{void}, or an
  116. integer that fits into a @code{size_t} or @code{ssize_t}.
  117. You can also create smobs that have two or three immediate words, and
  118. when these words suffice to store all data, it is more efficient to use
  119. these super-sized smobs instead of using a normal smob plus a memory
  120. block. @xref{Double Smobs}, for their discussion.
  121. Guile provides functions for managing memory which are often helpful
  122. when implementing smobs. @xref{Memory Blocks}.
  123. To retrieve the immediate word of a smob, you use the macro
  124. @code{SCM_SMOB_DATA}. It can be set with @code{SCM_SET_SMOB_DATA}.
  125. The 16 extra bits can be accessed with @code{SCM_SMOB_FLAGS} and
  126. @code{SCM_SET_SMOB_FLAGS}.
  127. The two macros @code{SCM_SMOB_DATA} and @code{SCM_SET_SMOB_DATA} treat
  128. the immediate word as if it were of type @code{scm_t_bits}, which is
  129. an unsigned integer type large enough to hold a pointer to
  130. @code{void}. Thus you can use these macros to store arbitrary
  131. pointers in the smob word.
  132. When you want to store a @code{SCM} value directly in the immediate
  133. word of a smob, you should use the macros @code{SCM_SMOB_OBJECT} and
  134. @code{SCM_SET_SMOB_OBJECT} to access it.
  135. Creating a smob instance can be tricky when it consists of multiple
  136. steps that allocate resources and might fail. It is recommended that
  137. you go about creating a smob in the following way:
  138. @itemize
  139. @item
  140. Allocate the memory block for holding the data with
  141. @code{scm_gc_malloc}.
  142. @item
  143. Initialize it to a valid state without calling any functions that might
  144. cause a non-local exits. For example, initialize pointers to NULL.
  145. Also, do not store @code{SCM} values in it that must be protected.
  146. Initialize these fields with @code{SCM_BOOL_F}.
  147. A valid state is one that can be safely acted upon by the @emph{mark}
  148. and @emph{free} functions of your smob type.
  149. @item
  150. Create the smob using @code{SCM_NEWSMOB}, passing it the initialized
  151. memory block. (This step will always succeed.)
  152. @item
  153. Complete the initialization of the memory block by, for example,
  154. allocating additional resources and making it point to them.
  155. @end itemize
  156. This procedure ensures that the smob is in a valid state as soon as it
  157. exists, that all resources that are allocated for the smob are
  158. properly associated with it so that they can be properly freed, and
  159. that no @code{SCM} values that need to be protected are stored in it
  160. while the smob does not yet competely exist and thus can not protect
  161. them.
  162. Continuing the example from above, if the global variable
  163. @code{image_tag} contains a tag returned by @code{scm_make_smob_type},
  164. here is how we could construct a smob whose immediate word contains a
  165. pointer to a freshly allocated @code{struct image}:
  166. @example
  167. SCM
  168. make_image (SCM name, SCM s_width, SCM s_height)
  169. @{
  170. SCM smob;
  171. struct image *image;
  172. int width = scm_to_int (s_width);
  173. int height = scm_to_int (s_height);
  174. /* Step 1: Allocate the memory block.
  175. */
  176. image = (struct image *) scm_gc_malloc (sizeof (struct image), "image");
  177. /* Step 2: Initialize it with straight code.
  178. */
  179. image->width = width;
  180. image->height = height;
  181. image->pixels = NULL;
  182. image->name = SCM_BOOL_F;
  183. image->update_func = SCM_BOOL_F;
  184. /* Step 3: Create the smob.
  185. */
  186. SCM_NEWSMOB (smob, image_tag, image);
  187. /* Step 4: Finish the initialization.
  188. */
  189. image->name = name;
  190. image->pixels = scm_gc_malloc (width * height, "image pixels");
  191. return smob;
  192. @}
  193. @end example
  194. Let us look at what might happen when @code{make_image} is called.
  195. The conversions of @var{s_width} and @var{s_height} to @code{int}s might
  196. fail and signal an error, thus causing a non-local exit. This is not a
  197. problem since no resources have been allocated yet that would have to be
  198. freed.
  199. The allocation of @var{image} in step 1 might fail, but this is likewise
  200. no problem.
  201. Step 2 can not exit non-locally. At the end of it, the @var{image}
  202. struct is in a valid state for the @code{mark_image} and
  203. @code{free_image} functions (see below).
  204. Step 3 can not exit non-locally either. This is guaranteed by Guile.
  205. After it, @var{smob} contains a valid smob that is properly initialized
  206. and protected, and in turn can properly protect the Scheme values in its
  207. @var{image} struct.
  208. But before the smob is completely created, @code{SCM_NEWSMOB} might
  209. cause the garbage collector to run. During this garbage collection, the
  210. @code{SCM} values in the @var{image} struct would be invisible to Guile.
  211. It only gets to know about them via the @code{mark_image} function, but
  212. that function can not yet do its job since the smob has not been created
  213. yet. Thus, it is important to not store @code{SCM} values in the
  214. @var{image} struct until after the smob has been created.
  215. Step 4, finally, might fail and cause a non-local exit. In that case,
  216. the complete creation of the smob has not been successful, but it does
  217. nevertheless exist in a valid state. It will eventually be freed by
  218. the garbage collector, and all the resources that have been allocated
  219. for it will be correctly freed by @code{free_image}.
  220. @node Type checking
  221. @subsection Type checking
  222. Functions that operate on smobs should check that the passed
  223. @code{SCM} value indeed is a suitable smob before accessing its data.
  224. They can do this with @code{scm_assert_smob_type}.
  225. For example, here is a simple function that operates on an image smob,
  226. and checks the type of its argument.
  227. @example
  228. SCM
  229. clear_image (SCM image_smob)
  230. @{
  231. int area;
  232. struct image *image;
  233. scm_assert_smob_type (image_tag, image_smob);
  234. image = (struct image *) SCM_SMOB_DATA (image_smob);
  235. area = image->width * image->height;
  236. memset (image->pixels, 0, area);
  237. /* Invoke the image's update function.
  238. */
  239. if (scm_is_true (image->update_func))
  240. scm_call_0 (image->update_func);
  241. scm_remember_upto_here_1 (image_smob);
  242. return SCM_UNSPECIFIED;
  243. @}
  244. @end example
  245. See @ref{Remembering During Operations} for an explanation of the call
  246. to @code{scm_remember_upto_here_1}.
  247. @node Garbage Collecting Smobs
  248. @subsection Garbage Collecting Smobs
  249. Once a smob has been released to the tender mercies of the Scheme
  250. system, it must be prepared to survive garbage collection. Guile calls
  251. the @emph{mark} and @emph{free} functions of the smob to manage this.
  252. As described in more detail elsewhere (@pxref{Conservative GC}), every
  253. object in the Scheme system has a @dfn{mark bit}, which the garbage
  254. collector uses to tell live objects from dead ones. When collection
  255. starts, every object's mark bit is clear. The collector traces pointers
  256. through the heap, starting from objects known to be live, and sets the
  257. mark bit on each object it encounters. When it can find no more
  258. unmarked objects, the collector walks all objects, live and dead, frees
  259. those whose mark bits are still clear, and clears the mark bit on the
  260. others.
  261. The two main portions of the collection are called the @dfn{mark phase},
  262. during which the collector marks live objects, and the @dfn{sweep
  263. phase}, during which the collector frees all unmarked objects.
  264. The mark bit of a smob lives in a special memory region. When the
  265. collector encounters a smob, it sets the smob's mark bit, and uses the
  266. smob's type tag to find the appropriate @emph{mark} function for that
  267. smob. It then calls this @emph{mark} function, passing it the smob as
  268. its only argument.
  269. The @emph{mark} function is responsible for marking any other Scheme
  270. objects the smob refers to. If it does not do so, the objects' mark
  271. bits will still be clear when the collector begins to sweep, and the
  272. collector will free them. If this occurs, it will probably break, or at
  273. least confuse, any code operating on the smob; the smob's @code{SCM}
  274. values will have become dangling references.
  275. To mark an arbitrary Scheme object, the @emph{mark} function calls
  276. @code{scm_gc_mark}.
  277. Thus, here is how we might write @code{mark_image}:
  278. @example
  279. @group
  280. SCM
  281. mark_image (SCM image_smob)
  282. @{
  283. /* Mark the image's name and update function. */
  284. struct image *image = (struct image *) SCM_SMOB_DATA (image_smob);
  285. scm_gc_mark (image->name);
  286. scm_gc_mark (image->update_func);
  287. return SCM_BOOL_F;
  288. @}
  289. @end group
  290. @end example
  291. Note that, even though the image's @code{update_func} could be an
  292. arbitrarily complex structure (representing a procedure and any values
  293. enclosed in its environment), @code{scm_gc_mark} will recurse as
  294. necessary to mark all its components. Because @code{scm_gc_mark} sets
  295. an object's mark bit before it recurses, it is not confused by
  296. circular structures.
  297. As an optimization, the collector will mark whatever value is returned
  298. by the @emph{mark} function; this helps limit depth of recursion during
  299. the mark phase. Thus, the code above should really be written as:
  300. @example
  301. @group
  302. SCM
  303. mark_image (SCM image_smob)
  304. @{
  305. /* Mark the image's name and update function. */
  306. struct image *image = (struct image *) SCM_SMOB_DATA (image_smob);
  307. scm_gc_mark (image->name);
  308. return image->update_func;
  309. @}
  310. @end group
  311. @end example
  312. Finally, when the collector encounters an unmarked smob during the sweep
  313. phase, it uses the smob's tag to find the appropriate @emph{free}
  314. function for the smob. It then calls that function, passing it the smob
  315. as its only argument.
  316. The @emph{free} function must release any resources used by the smob.
  317. However, it must not free objects managed by the collector; the
  318. collector will take care of them. For historical reasons, the return
  319. type of the @emph{free} function should be @code{size_t}, an unsigned
  320. integral type; the @emph{free} function should always return zero.
  321. Here is how we might write the @code{free_image} function for the image
  322. smob type:
  323. @example
  324. size_t
  325. free_image (SCM image_smob)
  326. @{
  327. struct image *image = (struct image *) SCM_SMOB_DATA (image_smob);
  328. scm_gc_free (image->pixels, image->width * image->height, "image pixels");
  329. scm_gc_free (image, sizeof (struct image), "image");
  330. return 0;
  331. @}
  332. @end example
  333. During the sweep phase, the garbage collector will clear the mark bits
  334. on all live objects. The code which implements a smob need not do this
  335. itself.
  336. There is no way for smob code to be notified when collection is
  337. complete.
  338. It is usually a good idea to minimize the amount of processing done
  339. during garbage collection; keep the @emph{mark} and @emph{free}
  340. functions very simple. Since collections occur at unpredictable times,
  341. it is easy for any unusual activity to interfere with normal code.
  342. @node Garbage Collecting Simple Smobs
  343. @subsection Garbage Collecting Simple Smobs
  344. It is often useful to define very simple smob types --- smobs which have
  345. no data to mark, other than the cell itself, or smobs whose immediate
  346. data word is simply an ordinary Scheme object, to be marked recursively.
  347. Guile provides some functions to handle these common cases; you can use
  348. this function as your smob type's @emph{mark} function, if your smob's
  349. structure is simple enough.
  350. If the smob refers to no other Scheme objects, then no action is
  351. necessary; the garbage collector has already marked the smob cell
  352. itself. In that case, you can use zero as your mark function.
  353. If the smob refers to exactly one other Scheme object via its first
  354. immediate word, you can use @code{scm_markcdr} as its mark function.
  355. Its definition is simply:
  356. @smallexample
  357. SCM
  358. scm_markcdr (SCM obj)
  359. @{
  360. return SCM_SMOB_OBJECT (obj);
  361. @}
  362. @end smallexample
  363. @node Remembering During Operations
  364. @subsection Remembering During Operations
  365. @cindex remembering
  366. It's important that a smob is visible to the garbage collector
  367. whenever its contents are being accessed. Otherwise it could be freed
  368. while code is still using it.
  369. For example, consider a procedure to convert image data to a list of
  370. pixel values.
  371. @example
  372. SCM
  373. image_to_list (SCM image_smob)
  374. @{
  375. struct image *image;
  376. SCM lst;
  377. int i;
  378. scm_assert_smob_type (image_tag, image_smob);
  379. image = (struct image *) SCM_SMOB_DATA (image_smob);
  380. lst = SCM_EOL;
  381. for (i = image->width * image->height - 1; i >= 0; i--)
  382. lst = scm_cons (scm_from_char (image->pixels[i]), lst);
  383. scm_remember_upto_here_1 (image_smob);
  384. return lst;
  385. @}
  386. @end example
  387. In the loop, only the @code{image} pointer is used and the C compiler
  388. has no reason to keep the @code{image_smob} value anywhere. If
  389. @code{scm_cons} results in a garbage collection, @code{image_smob} might
  390. not be on the stack or anywhere else and could be freed, leaving the
  391. loop accessing freed data. The use of @code{scm_remember_upto_here_1}
  392. prevents this, by creating a reference to @code{image_smob} after all
  393. data accesses.
  394. There's no need to do the same for @code{lst}, since that's the return
  395. value and the compiler will certainly keep it in a register or
  396. somewhere throughout the routine.
  397. The @code{clear_image} example previously shown (@pxref{Type checking})
  398. also used @code{scm_remember_upto_here_1} for this reason.
  399. It's only in quite rare circumstances that a missing
  400. @code{scm_remember_upto_here_1} will bite, but when it happens the
  401. consequences are serious. Fortunately the rule is simple: whenever
  402. calling a Guile library function or doing something that might, ensure
  403. that the @code{SCM} of a smob is referenced past all accesses to its
  404. insides. Do this by adding an @code{scm_remember_upto_here_1} if
  405. there are no other references.
  406. In a multi-threaded program, the rule is the same. As far as a given
  407. thread is concerned, a garbage collection still only occurs within a
  408. Guile library function, not at an arbitrary time. (Guile waits for all
  409. threads to reach one of its library functions, and holds them there
  410. while the collector runs.)
  411. @node Double Smobs
  412. @subsection Double Smobs
  413. Smobs are called smob because they are small: they normally have only
  414. room for one @code{void*} or @code{SCM} value plus 16 bits. The
  415. reason for this is that smobs are directly implemented by using the
  416. low-level, two-word cells of Guile that are also used to implement
  417. pairs, for example. (@pxref{Data Representation} for the details.)
  418. One word of the two-word cells is used for @code{SCM_SMOB_DATA} (or
  419. @code{SCM_SMOB_OBJECT}), the other contains the 16-bit type tag and
  420. the 16 extra bits.
  421. In addition to the fundamental two-word cells, Guile also has
  422. four-word cells, which are appropriately called @dfn{double cells}.
  423. You can use them for @dfn{double smobs} and get two more immediate
  424. words of type @code{scm_t_bits}.
  425. A double smob is created with @code{SCM_NEWSMOB2} or
  426. @code{SCM_NEWSMOB3} instead of @code{SCM_NEWSMOB}. Its immediate
  427. words can be retrieved as @code{scm_t_bits} with
  428. @code{SCM_SMOB_DATA_2} and @code{SCM_SMOB_DATA_3} in addition to
  429. @code{SCM_SMOB_DATA}. Unsurprisingly, the words can be set to
  430. @code{scm_t_bits} values with @code{SCM_SET_SMOB_DATA_2} and
  431. @code{SCM_SET_SMOB_DATA_3}.
  432. Of course there are also @code{SCM_SMOB_OBJECT_2},
  433. @code{SCM_SMOB_OBJECT_3}, @code{SCM_SET_SMOB_OBJECT_2}, and
  434. @code{SCM_SET_SMOB_OBJECT_3}.
  435. @node The Complete Example
  436. @subsection The Complete Example
  437. Here is the complete text of the implementation of the image datatype,
  438. as presented in the sections above. We also provide a definition for
  439. the smob's @emph{print} function, and make some objects and functions
  440. static, to clarify exactly what the surrounding code is using.
  441. As mentioned above, you can find this code in the Guile distribution, in
  442. @file{doc/example-smob}. That directory includes a makefile and a
  443. suitable @code{main} function, so you can build a complete interactive
  444. Guile shell, extended with the datatypes described here.)
  445. @example
  446. /* file "image-type.c" */
  447. #include <stdlib.h>
  448. #include <libguile.h>
  449. static scm_t_bits image_tag;
  450. struct image @{
  451. int width, height;
  452. char *pixels;
  453. /* The name of this image */
  454. SCM name;
  455. /* A function to call when this image is
  456. modified, e.g., to update the screen,
  457. or SCM_BOOL_F if no action necessary */
  458. SCM update_func;
  459. @};
  460. static SCM
  461. make_image (SCM name, SCM s_width, SCM s_height)
  462. @{
  463. SCM smob;
  464. struct image *image;
  465. int width = scm_to_int (s_width);
  466. int height = scm_to_int (s_height);
  467. /* Step 1: Allocate the memory block.
  468. */
  469. image = (struct image *) scm_gc_malloc (sizeof (struct image), "image");
  470. /* Step 2: Initialize it with straight code.
  471. */
  472. image->width = width;
  473. image->height = height;
  474. image->pixels = NULL;
  475. image->name = SCM_BOOL_F;
  476. image->update_func = SCM_BOOL_F;
  477. /* Step 3: Create the smob.
  478. */
  479. SCM_NEWSMOB (smob, image_tag, image);
  480. /* Step 4: Finish the initialization.
  481. */
  482. image->name = name;
  483. image->pixels = scm_gc_malloc (width * height, "image pixels");
  484. return smob;
  485. @}
  486. SCM
  487. clear_image (SCM image_smob)
  488. @{
  489. int area;
  490. struct image *image;
  491. scm_assert_smob_type (image_tag, image_smob);
  492. image = (struct image *) SCM_SMOB_DATA (image_smob);
  493. area = image->width * image->height;
  494. memset (image->pixels, 0, area);
  495. /* Invoke the image's update function.
  496. */
  497. if (scm_is_true (image->update_func))
  498. scm_call_0 (image->update_func);
  499. scm_remember_upto_here_1 (image_smob);
  500. return SCM_UNSPECIFIED;
  501. @}
  502. static SCM
  503. mark_image (SCM image_smob)
  504. @{
  505. /* Mark the image's name and update function. */
  506. struct image *image = (struct image *) SCM_SMOB_DATA (image_smob);
  507. scm_gc_mark (image->name);
  508. return image->update_func;
  509. @}
  510. static size_t
  511. free_image (SCM image_smob)
  512. @{
  513. struct image *image = (struct image *) SCM_SMOB_DATA (image_smob);
  514. scm_gc_free (image->pixels, image->width * image->height, "image pixels");
  515. scm_gc_free (image, sizeof (struct image), "image");
  516. return 0;
  517. @}
  518. static int
  519. print_image (SCM image_smob, SCM port, scm_print_state *pstate)
  520. @{
  521. struct image *image = (struct image *) SCM_SMOB_DATA (image_smob);
  522. scm_puts ("#<image ", port);
  523. scm_display (image->name, port);
  524. scm_puts (">", port);
  525. /* non-zero means success */
  526. return 1;
  527. @}
  528. void
  529. init_image_type (void)
  530. @{
  531. image_tag = scm_make_smob_type ("image", sizeof (struct image));
  532. scm_set_smob_mark (image_tag, mark_image);
  533. scm_set_smob_free (image_tag, free_image);
  534. scm_set_smob_print (image_tag, print_image);
  535. scm_c_define_gsubr ("clear-image", 1, 0, 0, clear_image);
  536. scm_c_define_gsubr ("make-image", 3, 0, 0, make_image);
  537. @}
  538. @end example
  539. Here is a sample build and interaction with the code from the
  540. @file{example-smob} directory, on the author's machine:
  541. @example
  542. zwingli:example-smob$ make CC=gcc
  543. gcc `guile-config compile` -c image-type.c -o image-type.o
  544. gcc `guile-config compile` -c myguile.c -o myguile.o
  545. gcc image-type.o myguile.o `guile-config link` -o myguile
  546. zwingli:example-smob$ ./myguile
  547. guile> make-image
  548. #<primitive-procedure make-image>
  549. guile> (define i (make-image "Whistler's Mother" 100 100))
  550. guile> i
  551. #<image Whistler's Mother>
  552. guile> (clear-image i)
  553. guile> (clear-image 4)
  554. ERROR: In procedure clear-image in expression (clear-image 4):
  555. ERROR: Wrong type (expecting image): 4
  556. ABORT: (wrong-type-arg)
  557. Type "(backtrace)" to get more information.
  558. guile>
  559. @end example