2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 1999--2012 Han-Wen Nienhuys <hanwen@xs4all.nl>
6 LilyPond is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 LilyPond is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
23 #include "lily-guile.hh"
27 Smobs are GUILEs mechanism of exporting C(++) objects to the Scheme
28 world. They are documented in the GUILE manual.
31 In LilyPond, smobs are created from C++ objects through macros.
32 There are two types of smob objects.
34 1. Simple smobs are intended for simple objects like numbers:
35 immutable objects that can be copied without change of meaning.
37 To obtain an SCM version of a simple smob, use the member function
40 Simple smobs are created by adding the
41 DECLARE_SIMPLE_SMOBS(Classname) to the declaration
43 A simple smob is only optionally under the reign of the GUILE
44 garbage collector: its usual life time is that of a normal C++
45 object. While a smobbed_copy () is fully under control of the
46 garbage collector and will have its mark_smob function called during
47 garbage collection, an automatic variable of this type will not have
48 mark_smob called, but rather have its memory image in the call stack
49 scanned for contained non-immediate SCM values. Anything requiring
50 more complex mark_smob behavior is not suitable for a simple smob.
52 When you create a smobbed_copy, the _copy_ is fully managed by the
53 GUILE memory system. As a corollary, multiple smobbed_copy calls
54 yield multiple GUILE objects generally not eq? to each other.
56 2. Complex smobs are objects that have an identity. These objects
57 carry this identity in the form of a self_scm () method, which is a
58 SCM pointer to the object itself. Complex smobs are always under
59 control of the GUILE memory system.
61 The constructor for a complex smob should have 3 steps:
63 * initialize all SCM members to an immediate value (like SCM_EOL)
65 * call smobify_self ()
67 * initialize SCM members
71 Complex_smob::Complex_smob () {
72 scm_member_ = SCM_EOL;
74 scm_member_ = <..what you want to store..>
77 after construction, the self_scm () field of a complex smob is
78 protected from Garbage Collection. This protection should be
79 removed once the object is put into another (reachable) Scheme data
82 Complex_smob *p = new Complex_smob;
83 list = scm_cons (p->self_scm (), list);
86 Since unprotect returns the SCM object itself, this particular case
89 Complex_smob *p = new Complex_smob;
90 list = scm_cons (p->unprotect (), list);
92 Complex smobs are made with DECLARE_SMOBS (Classname) in the class
97 Common public methods to C++ smob objects:
99 unsmob (SCM x) - unpacks X and returns pointer to the C++ object, or 0
100 if it has the wrong type.
102 SCM equal_p (SCM a, SCM b) - compare A and B. Returns a Scheme boolean
107 For implementating a class, the following should be provided
109 - an equal_p () function (a default is in the
110 IMPLEMENT_DEFAULT_EQUAL_P macro in ly-smobs.icc)
112 - mark_smob () function, that calls scm_gc_mark () on all Scheme
115 - a print_smob () function, that displays a representation for
118 - A call to one of the IMPLEMENT_SMOBS or IMPLEMENT_SIMPLE_SMOBS macros
119 from file "ly-smobs.icc"
122 #define DECLARE_SIMPLE_SMOBS(CL) \
124 SCM smobbed_copy () const; \
125 DECLARE_BASE_SMOBS (CL)
127 #define DECLARE_BASE_SMOBS(CL) \
128 friend class Non_existent_class; \
130 static const char* smob_name_; \
131 static scm_t_bits smob_tag_; \
132 static SCM mark_smob (SCM); \
133 static size_t free_smob (SCM s); \
134 static int print_smob (SCM s, SCM p, scm_print_state*); \
136 static SCM equal_p (SCM a, SCM b); \
137 static CL *unsmob (SCM s) __attribute__((pure)) \
139 if (SCM_NIMP (s) && SCM_CELL_TYPE (s) == smob_tag_) \
140 return (CL *) SCM_CELL_WORD_1 (s); \
144 static SCM smob_p (SCM); \
145 static void init_smobs (); \
148 #define DECLARE_SMOBS(CL) \
149 DECLARE_BASE_SMOBS (CL) \
152 SCM unprotected_smobify_self (); \
154 void smobify_self (); \
156 SCM protection_cons_; \
160 SCM self_scm () const { return self_scm_; } \
163 #define DECLARE_UNSMOB(CL, name) \
165 unsmob_ ## name (SCM s) \
167 return CL::unsmob (s); \
170 #define DECLARE_TYPE_P(CL) extern SCM CL ## _type_p_proc
172 void protect_smob (SCM smob, SCM *prot_cons);
173 void unprotect_smob (SCM smob, SCM *prot_cons);
175 extern bool parsed_objects_should_be_dead;
178 static vector<parsed_dead *> elements;
183 data = SCM_UNDEFINED;
187 parsed_dead () : data (SCM_UNDEFINED)
189 elements.push_back (this);
191 void checkin (SCM arg) { data = arg; }
192 static SCM readout ();
196 #define ASSERT_LIVE_IS_ALLOWED(arg) \
198 static parsed_dead pass_here; \
199 if (parsed_objects_should_be_dead) \
200 pass_here.checkin (arg); \
203 #define ASSERT_LIVE_IS_ALLOWED(arg) do { (void)(arg); } \
207 #endif /* SMOBS_HH */