/
/smoke.xml
1 <?xml version="1.0"?>
2 <!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
3 "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
4 <chapter id="usage">
5 <title>Usage</title>
6 <para></para>
7 <section><title>Symbols</title>
8 <para>
9 C++ names are converted to Lisp symbols by converting <code>camelCase</code>
10 to <code>camel-case</code>. Underscores <code>#\_</code> are replaced with
11 <code>#\-</code> and a leading uppercase K or Q is removed.
12 </para>
13 <informalexample>
14 <para>
15 E.g.: <code>QHelloWorld_foo</code> becomes <code>hello-world-foo</code>.
16 </para>
17 </informalexample>
18 </section>
19
20 <section id="classes"><title>Class</title>
21 <para>
22 C++ classes have a corresponding CLOS class. The can be used like any CLOS class; E.g:
23 to make a <code>QObject</code> instance:
24 <informalexample>
25 <programlisting language="lisp">
26 (make-instance '<classname>qt:object</classname>)
27 </programlisting>
28 </informalexample>
29 Supply arguments as list to the <code>:args</code> keyword:
30 <informalexample>
31 <programlisting language="lisp">
32 (let ((parent (make-instance '<classname>qt:object</classname>)))
33 (make-instance '<classname>qt:object</classname> :args (list parent)))
34 </programlisting>
35 </informalexample>
36 or use <code>:arg0</code>, <code>:arg1</code> and <code>:arg2</code>.
37 <informalexample>
38 <programlisting language="lisp">
39 (let ((parent (make-instance '<classname>qt:object</classname>)))
40 (make-instance '<classname>qt:object</classname> :arg0 parent))
41 </programlisting>
42 </informalexample>
43 </para>
44 <para>
45 To extend a C++ class you have to use <classname>cxx:class</classname> as metaclass:
46 <informalexample>
47 <programlisting language="lisp">
48 (defclass my-object (<classname>qt:object</classname>)
49 ()
50 (:metaclass <classname>cxx:class</classname>))
51
52 (make-instance 'my-object)
53 </programlisting>
54 </informalexample>
55 The first superclass must be a Smoke class. When you define a class that has several Smoke superclasses,
56 they will be constructed with their default constructor. For the first Smoke superclass you can supply arguments
57 with the <code>:args</code> and <code>:arg0</code> etc. keywords.
58 <informalexample>
59 <programlisting language="lisp">
60 (defclass my-graphics-object (<classname>qt:object</classname> <classname>qt:graphics-item</classname>)
61 ()
62 (:metaclass <classname>cxx:class</classname>))
63 </programlisting>
64 </informalexample>
65 </para>
66 </section>
67
68 <section id="methods"><title>Methods</title>
69 <para>
70 C++ methods are generic functions in the <package>:cxx</package> package.
71 </para>
72 <para>
73 The C++ method call: <code>myInstance->frob(1);</code> is in Lisp:
74 <informalexample>
75 <programlisting language="lisp">(frob my-instance 1)</programlisting>
76 </informalexample>
77 </para>
78 <section><title>Overload Resolution</title>
79 <para>
80 C++ style overload resolution with conversion sequences is supported. For example this:
81 <informalexample>
82 <programlisting language="lisp">
83 (<genericfunction>cxx:set-pen</genericfunction> (make-instance '<classname>qt:painter</classname>) (make-instance '<classname>qt:color</classname> :args '("green")))
84 </programlisting>
85 </informalexample>
86 is equivalent to:
87 <informalexample>
88 <programlisting language="lisp">
89 (<genericfunction>cxx:set-pen</genericfunction> (make-instance '<classname>qt:painter</classname>) "green")
90 </programlisting>
91 </informalexample>
92 In the second case a temporary <classname>qt:color</classname> instance is implicitly created.
93 </para>
94 </section>
95
96 <section><title>Setter Methods</title>
97 <para>
98 Instead of calling a setter method that takes no additional arguments,
99 <informalexample>
100 <programlisting language="lisp">
101 (<genericfunction>cxx:set-object-name</genericfunction> (make-instance '<classname>qt:object</classname>) "foo")
102 </programlisting>
103 </informalexample>
104 you can use its <code>setf</code>able getter.
105 <informalexample>
106 <programlisting language="lisp">
107 (setf (<genericfunction>cxx:object-name</genericfunction> (make-instance '<classname>qt:object</classname>)) "foo")
108 </programlisting>
109 </informalexample>
110 </para>
111 </section>
112
113 <section><title><code>defmethod</code></title>
114 <para>
115 You can extend the <package>:cxx</package> generic functions by
116 adding methods. <code>:around</code>, <code>:before</code>, <code>:after</code>
117 and <code>(call-next-method)</code> are supported.
118 </para>
119 <informalexample>
120 <programlisting language="lisp">(defclass the-object-does-nothing (<classname>qt:object</classname>)
121 ()
122 (:metaclass <classname>cxx:class</classname>))
123
124 (defmethod <genericfunction>cxx:timer-event</genericfunction> ((object the-object-does-nothing) event)
125 (declare (ignore object event))
126 (call-next-method))
127 </programlisting>
128 </informalexample>
129 <para>
130 <package>:cxx</package> generic functions can be overload by argument count. Lambda list
131 keywords (e.g.: <code>&amp;rest</code> and <code>&amp;key</code>) are not supported.
132 </para>
133 <note><para>
134 Make sure you have the right number of arguments when adding a method; otherwise it will
135 not be called.
136 </para></note>
137 <caution><para>
138 The arguments of the method might have dynamic extend; i.e.: they are only valid in the body of the method.
139 </para></caution>
140 <section><title>Condition</title>
141 <para>
142 Unwinding of the C++ stack is not supported. This means that you must not invoke a restart that skips any foreign function.
143 You will most likely encounter this problem when an error is signaled in a virtual method you have overwritten.
144 <footnote>
145 <para>
146 For example an event handler that is called from the C++ library.
147 </para>
148 </footnote>. For this case restarts are provide that allow to return a value for the failed method,
149 call the default C++ implementation instead (something like <code>#'call-next-method</code>) or retry.
150 </para>
151 </section>
152 </section>
153 <section><title>Operators</title>
154 <para>
155 Instead of using the various <code>cxx:operator</code> methods you can use their Lisp equivalent
156 in the <package>:cxx</package> package.
157 <simplelist type='horiz' columns='4'>
158 <member><code>cxx:&gt;</code></member> <!-- FIXME mb.document handling of no alphnum chars !-->
159 <member><code>cxx:&gt;=</code></member>
160 </simplelist>
161 <simplelist type='horiz' columns='4'>
162 <member><code>cxx:=</code></member>
163 <member><code>cxx:/=</code></member>
164 </simplelist>
165 <simplelist type='horiz' columns='4'>
166 <member><code>cxx:&lt;=</code></member>
167 <member><code>cxx:&lt;</code></member>
168 </simplelist>
169 <simplelist type='horiz' columns='4'>
170 <member><code>cxx:+</code></member>
171 <member><code>cxx:-</code></member>
172 <member><code>cxx:*</code></member>
173 <member><code>cxx:/</code></member>
174 <member><code>cxx:1+</code></member>
175 <member><code>cxx:1-</code></member>
176 </simplelist>
177 <simplelist type='horiz' columns='4'>
178 <member><methodname>cxx:incf</methodname></member>
179 <member><methodname>cxx:decf</methodname></member>
180 </simplelist>
181 <simplelist>
182 <member><methodname>cxx:aref</methodname></member>
183 </simplelist>
184 </para>
185 </section>
186 </section>
187
188 <section id="static_methods"><title>Static Methods</title>
189 <para>
190 The static C++ method <code>QByteArray::number(int n, int base=10)</code>
191 can be called by:
192 <informalexample>
193 <programlisting language="lisp">(<methodname>qt:byte-array.number</methodname> 37)</programlisting>
194 </informalexample>
195 which is equivalent to the C++ code <code>QByteArray::number(37);</code>.
196 Or with:
197 <informalexample>
198 <programlisting language="lisp">(<genericfunction>cxx:number</genericfunction> (find-class '<classname>qt:byte-array</classname>) 37)</programlisting>
199 </informalexample>
200 or:
201 <informalexample>
202 <programlisting language="lisp">(<genericfunction>cxx:number</genericfunction> (make-instance '<classname>qt:byte-array</classname>) 37)</programlisting>
203 </informalexample>
204 </para>
205 </section>
206
207 <section id="constants"><title>Constants</title>
208 <para>
209 C++ Class enums available as constants. E.g.:
210 <code>QColor::Rgb</code> is <constant>qt:color.+rgb+</constant>.
211 See <package>:cxx-support</package>.
212 </para>
213 </section>
214
215 <section id="members"><title>Member variables</title>
216 <para>
217 C++ member variables of an instance can be accessed by using <code>slot-value</code>; e.g.:
218 <informalexample>
219 <programlisting language="lisp">(slot-value (make-instance 'qt:object) :static-meta-object)</programlisting>
220 </informalexample>
221 or
222 <informalexample>
223 <programlisting language="lisp">(slot-value (find-class 'qt:object) :static-meta-object)</programlisting>
224 </informalexample>
225 Usually they can also be accessed using methods from the <package>:cxx</package> package.
226 </para>
227 </section>
228
229 <section id="gc"><title>Garbage Collection</title>
230 <para>
231 You should be able to use C++ Class instances like normal Lisp object.
232 </para>
233 <para>
234 C++ classes are automatically deleted when their Lisp object gets garbage collected;
235 except when they (QObjects) have a parent and thus the parent is responsible for
236 their deletion. When a <classname>qt:object</classname> has a parent, a strong
237 reference is kept to prevent the garbage collection removing it until the parent is deleted.
238 </para>
239 <caution>
240 <para>
241 Ownership transfer for non QObject instances is mostly unimplemented.
242 </para>
243 </caution>
244 </section>
245
246 <section id="core-image"><title>Saving a Core Image</title>
247 <para>
248 For near instant startup you can save an image. Since saving C++ instances is not supported,
249 it is best to save the image immediately after loading the packages.
250 </para>
251
252 <note><para>
253 Initializing the Smoke bindings when the image is loaded is implementation dependent. It is implemented
254 for SBCL and Clozure CL.
255 </para></note>
256
257 <section><title>SBCL</title>
258 <para>To save an image in SBCL you can use:
259 <ulink url="http://www.sbcl.org/manual/Saving-a-Core-Image.html"><code>sb-ext:save-lisp-and-die</code></ulink>
260 </para>
261
262 <section><title>Bundle</title>
263 <para>
264 To create a bundle containing an SBCL image and the required C wrappers libraries you can use
265 <methodname>smoke:save-bundle</methodname>.
266 The bundle is created using <ulink url="http://megastep.org/makeself/">makeself</ulink>.
267 See
268 <ulink url="http://tobias.rautenkranz.ch/darcsweb/darcsweb.cgi?r=cl-smoke/qt.examples;a=headblob;f=/make-bundle.sh">make-bundle.sh</ulink> in <package>:qt.examples</package> for an example.
269 </para>
270 </section>
271 </section>
272
273 <section><title>Clozure CL</title>
274 <para>
275 To save an image in CCL
276 <ulink url="http://ccl.clozure.com/manual/chapter4.7.html#Saving-Applications">
277 <code>ccl:save-application</code></ulink> is usually used.
278 </para>
279 <caution>
280 <para>
281 To allow the image to find the C wrapper libraries, they have to be installed with:
282 <informalexample>
283 <programlisting>
284 sudo make install
285 </programlisting>
286 </informalexample>
287 run in the <filename>smoke/</filename> and <filename>qt/</filename> directory.
288 </para>
289 </caution>
290 </section>
291
292 </section>
293
294 </chapter>