2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 2016 David Kastrup <dak@gnu.org>
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 // A callback wrapper creates a Scheme-callable version of a fixed C++
24 // function. It is generally used for calling template-generated
25 // trampoline functions leading to calling a particular member
26 // function on a given Smob.
28 // The class itself is not templated in order not to explode the
29 // number of smob types: each class can support a particular call
32 // Check the GET_LISTENER call for a typical use case.
36 class Callback_wrapper : public Simple_smob<Callback_wrapper>
38 // We use an ordinary function pointer pointing to a trampoline
39 // function (templated on the callback in question) instead of
40 // storing a member function pointer to a common base class like
41 // Smob_core. The additional code for the trampolines is negligible
42 // and the performance implications of using member function
43 // pointers in connection with inheritance are somewhat opaque as
44 // this involves an adjustment of the this pointer from Smob_core to
45 // the scope containing the callback.
46 SCM (*trampoline_) (SCM, SCM);
47 Callback_wrapper (SCM (*trampoline) (SCM, SCM))
48 : trampoline_ (trampoline)
49 { } // Private constructor, use only in make_smob
51 static const char * const type_p_name_; // = 0
52 LY_DECLARE_SMOB_PROC (&Callback_wrapper::call, 2, 0, 0)
53 SCM call (SCM target, SCM arg)
55 return trampoline_ (target, arg);
57 // Callback wrappers are for an unchanging entity, so we do the Lisp
58 // creation just once on the first call of make_smob. So we only
59 // get a single Callback_wrapper instance for each differently
60 // templated make_smob call.
61 template <SCM (*trampoline) (SCM, SCM)>
62 static SCM make_smob ()
65 scm_permanent_object (Callback_wrapper (trampoline).smobbed_copy ());
70 class Callback2_wrapper : public Simple_smob<Callback2_wrapper>
72 // See Callback_wrapper for the details. Callback2_wrapper just
73 // supports an additional SCM argument as compared to
74 // Callback_wrapper but is otherwise identical.
75 SCM (*trampoline_) (SCM, SCM, SCM);
76 Callback2_wrapper (SCM (*trampoline) (SCM, SCM, SCM))
77 : trampoline_ (trampoline)
78 { } // Private constructor, use only in make_smob
80 static const char * const type_p_name_; // = 0
81 LY_DECLARE_SMOB_PROC (&Callback2_wrapper::call, 3, 0, 0)
82 SCM call (SCM target, SCM arg1, SCM arg2)
84 return trampoline_ (target, arg1, arg2);
87 template <SCM (*trampoline) (SCM, SCM, SCM)>
88 static SCM make_smob ()
91 scm_permanent_object (Callback2_wrapper (trampoline).smobbed_copy ());
96 class Callback0_wrapper : public Simple_smob<Callback0_wrapper>
98 // See Callback_wrapper for the details. Callback0_wrapper does not
99 // pass arguments but is otherwise identical to Callback_wrapper.
100 SCM (*trampoline_) (SCM);
101 Callback0_wrapper (SCM (*trampoline) (SCM))
102 : trampoline_ (trampoline)
103 { } // Private constructor, use only in make_smob
105 static const char * const type_p_name_; // = 0
106 LY_DECLARE_SMOB_PROC (&Callback0_wrapper::call, 1, 0, 0)
107 SCM call (SCM target)
109 return trampoline_ (target);
112 template <SCM (*trampoline) (SCM)>
113 static SCM make_smob ()
116 scm_permanent_object (Callback0_wrapper (trampoline).smobbed_copy ());
119 // Since there are no arguments at all, we might as well provide
120 // default trampolines
121 template <class T, SCM (T::*p)()>
122 static SCM trampoline (SCM target)
124 T *t = LY_ASSERT_SMOB (T, target, 1);
128 template <class T, void (T::*p)()>
129 static SCM trampoline (SCM target)
131 T *t = LY_ASSERT_SMOB (T, target, 1);
133 return SCM_UNSPECIFIED;
136 template <class T, SCM (T::*p)()>
137 static SCM make_smob ()
139 return make_smob<trampoline<T, p> > ();
142 template <class T, void (T::*p)()>
143 static SCM make_smob ()
145 return make_smob<trampoline<T, p> > ();
149 // The following will usually be used unsmobbified, relying on its
150 // constituents being protected independently.
152 class Method_instance : public Simple_smob<Method_instance>
154 SCM method_, instance_;
156 static const char * const type_p_name_; // = 0
157 LY_DECLARE_SMOB_PROC (&Method_instance::call, 0, 0, 1)
160 return scm_apply_1 (method_, instance_, rest);
163 Method_instance (SCM method, SCM instance)
164 : method_ (method), instance_ (instance)
166 Method_instance (SCM method, Smob_core *instance)
167 : method_ (method), instance_ (instance->self_scm ())
169 SCM method () const { return method_; }
170 SCM instance () const { return instance_; }
171 SCM operator () () const
173 return scm_call_1 (method_, instance_);
175 SCM operator () (SCM arg) const
177 return scm_call_2 (method_, instance_, arg);
179 SCM operator () (SCM arg1, SCM arg2) const
181 return scm_call_3 (method_, instance_, arg1, arg2);
183 SCM mark_smob () const
185 scm_gc_mark (method_);