C++ member variable access
Annotate for file /smoke.xml
2009-04-05 tobias 1 <?xml version="1.0"?>
17:58:25 ' 2 <!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
' 3 "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
2009-07-06 tobias 4 <chapter id="usage">
2009-04-05 tobias 5 <title>Usage</title>
17:58:25 ' 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>
2009-06-04 tobias 13 <informalexample>
2009-04-05 tobias 14 <para>
17:58:25 ' 15 E.g.: <code>QHelloWorld_foo</code> becomes <code>hello-world-foo</code>.
' 16 </para>
2009-06-04 tobias 17 </informalexample>
2009-04-05 tobias 18 </section>
17:58:25 ' 19
2009-07-06 tobias 20 <section id="classes"><title>Class</title>
2009-04-05 tobias 21 <para>
17:58:25 ' 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>
2009-06-05 tobias 25 <programlisting language="lisp">
2009-04-05 tobias 26 (make-instance '<classname>qt:object</classname>)
17:58:25 ' 27 </programlisting>
' 28 </informalexample>
2009-04-17 tobias 29 Supply arguments as list to the <code>:args</code> keyword:
2009-04-05 tobias 30 <informalexample>
2009-06-05 tobias 31 <programlisting language="lisp">
2009-04-05 tobias 32 (let ((parent (make-instance '<classname>qt:object</classname>)))
2009-08-30 tobias 33 (make-instance '<classname>qt:object</classname> :args (list parent)))
2009-04-05 tobias 34 </programlisting>
17:58:25 ' 35 </informalexample>
2009-07-22 tobias 36 or use <code>:arg0</code>, <code>:arg1</code> and <code>:arg2</code>.
22:53:41 ' 37 <informalexample>
' 38 <programlisting language="lisp">
' 39 (let ((parent (make-instance '<classname>qt:object</classname>)))
2009-08-30 tobias 40 (make-instance '<classname>qt:object</classname> :arg0 parent))
2009-07-22 tobias 41 </programlisting>
22:53:41 ' 42 </informalexample>
2009-04-05 tobias 43 </para>
17:58:25 ' 44 <para>
' 45 To extend a C++ class you have to use <classname>cxx:class</classname> as metaclass:
' 46 <informalexample>
2009-06-05 tobias 47 <programlisting language="lisp">
2009-04-05 tobias 48 (defclass my-object (<classname>qt:object</classname>)
2009-08-30 tobias 49 ()
14:26:13 ' 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>))
2009-04-05 tobias 63 </programlisting>
17:58:25 ' 64 </informalexample>
' 65 </para>
' 66 </section>
' 67
2009-07-06 tobias 68 <section id="methods"><title>Methods</title>
2009-04-05 tobias 69 <para>
2009-06-04 tobias 70 C++ methods are generic functions in the <package>:cxx</package> package.
2009-04-05 tobias 71 </para>
17:58:25 ' 72 <para>
' 73 The C++ method call: <code>myInstance->frob(1);</code> is in Lisp:
' 74 <informalexample>
2009-06-05 tobias 75 <programlisting language="lisp">(frob my-instance 1)</programlisting>
2009-04-05 tobias 76 </informalexample>
17:58:25 ' 77 </para>
2009-04-17 tobias 78 <section><title>Overload Resolution</title>
15:32:31 ' 79 <para>
2009-05-12 tobias 80 C++ style overload resolution with conversion sequences is supported. For example this:
2009-04-17 tobias 81 <informalexample>
2009-06-05 tobias 82 <programlisting language="lisp">
2009-05-11 tobias 83 (<genericfunction>cxx:set-pen</genericfunction> (make-instance '<classname>qt:painter</classname>) (make-instance '<classname>qt:color</classname> :args '("green")))
2009-04-17 tobias 84 </programlisting>
15:32:31 ' 85 </informalexample>
' 86 is equivalent to:
' 87 <informalexample>
2009-06-05 tobias 88 <programlisting language="lisp">
2009-05-11 tobias 89 (<genericfunction>cxx:set-pen</genericfunction> (make-instance '<classname>qt:painter</classname>) "green")
2009-04-17 tobias 90 </programlisting>
15:32:31 ' 91 </informalexample>
' 92 In the second case a temporary <classname>qt:color</classname> instance is implicitly created.
' 93 </para>
' 94 </section>
' 95
2009-05-11 tobias 96 <section><title>Setter Methods</title>
20:19:30 ' 97 <para>
' 98 Instead of calling a setter method that takes no additional arguments,
' 99 <informalexample>
2009-06-05 tobias 100 <programlisting language="lisp">
2009-05-11 tobias 101 (<genericfunction>cxx:set-object-name</genericfunction> (make-instance '<classname>qt:object</classname>) "foo")
20:19:30 ' 102 </programlisting>
' 103 </informalexample>
' 104 you can use its <code>setf</code>able getter.
' 105 <informalexample>
2009-06-05 tobias 106 <programlisting language="lisp">
2009-05-11 tobias 107 (setf (<genericfunction>cxx:object-name</genericfunction> (make-instance '<classname>qt:object</classname>)) "foo")
20:19:30 ' 108 </programlisting>
' 109 </informalexample>
' 110 </para>
' 111 </section>
' 112
' 113 <section><title><code>defmethod</code></title>
2009-04-05 tobias 114 <para>
17:58:25 ' 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>
2009-04-12 tobias 119 <informalexample>
2009-06-05 tobias 120 <programlisting language="lisp">(defclass the-object-does-nothing (<classname>qt:object</classname>)
2009-08-30 tobias 121 ()
14:26:13 ' 122 (:metaclass <classname>cxx:class</classname>))
2009-04-12 tobias 123
2009-04-12 tobias 124 (defmethod <genericfunction>cxx:timer-event</genericfunction> ((object the-object-does-nothing) event)
2009-08-30 tobias 125 (declare (ignore object event))
14:26:13 ' 126 (call-next-method))
2009-04-12 tobias 127 </programlisting>
14:50:23 ' 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>
2009-06-04 tobias 137 <caution><para>
21:20:49 ' 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>
2009-06-03 tobias 140 <section><title>Condition</title>
22:31:34 ' 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.
2009-06-04 tobias 143 You will most likely encounter this problem when an error is signaled in a virtual method you have overwritten.
2009-06-03 tobias 144 <footnote>
22:31:34 ' 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>
2009-04-05 tobias 152 </section>
2009-04-12 tobias 153 <section><title>Operators</title>
20:56:16 ' 154 <para>
2009-05-11 tobias 155 Instead of using the various <code>cxx:operator</code> methods you can use their Lisp equivalent
2009-04-12 tobias 156 in the <package>:cxx</package> package.
2009-04-14 tobias 157 <simplelist type='horiz' columns='4'>
14:08:15 ' 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>
2009-04-12 tobias 184 </para>
20:56:16 ' 185 </section>
' 186 </section>
2009-04-05 tobias 187
2009-07-06 tobias 188 <section id="static_methods"><title>Static Methods</title>
2009-04-05 tobias 189 <para>
17:58:25 ' 190 The static C++ method <code>QByteArray::number(int n, int base=10)</code>
' 191 can be called by:
' 192 <informalexample>
2009-06-05 tobias 193 <programlisting language="lisp">(<methodname>qt:byte-array.number</methodname> 37)</programlisting>
2009-04-05 tobias 194 </informalexample>
17:58:25 ' 195 which is equivalent to the C++ code <code>QByteArray::number(37);</code>.
' 196 Or with:
' 197 <informalexample>
2009-06-05 tobias 198 <programlisting language="lisp">(<genericfunction>cxx:number</genericfunction> (find-class '<classname>qt:byte-array</classname>) 37)</programlisting>
2009-05-11 tobias 199 </informalexample>
20:19:30 ' 200 or:
' 201 <informalexample>
2009-06-05 tobias 202 <programlisting language="lisp">(<genericfunction>cxx:number</genericfunction> (make-instance '<classname>qt:byte-array</classname>) 37)</programlisting>
2009-04-05 tobias 203 </informalexample>
17:58:25 ' 204 </para>
' 205 </section>
' 206
2009-07-06 tobias 207 <section id="constants"><title>Constants</title>
2009-04-05 tobias 208 <para>
2009-08-30 tobias 209 C++ Class enums available as constants. E.g.:
14:26:13 ' 210 <code>QColor::Rgb</code> is <constant>qt:color.+rgb+</constant>.
' 211 See <package>:cxx-support</package>.
2009-04-05 tobias 212 </para>
17:58:25 ' 213 </section>
' 214
2010-04-03 tobias 215 <section id="members"><title>Member variables</title>
19:12:32 ' 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
2009-07-06 tobias 229 <section id="gc"><title>Garbage Collection</title>
2009-04-05 tobias 230 <para>
17:58:25 ' 231 You should be able to use C++ Class instances like normal Lisp object.
' 232 </para>
' 233 <para>
2009-06-04 tobias 234 C++ classes are automatically deleted when their Lisp object gets garbage collected;
2009-04-05 tobias 235 except when they (QObjects) have a parent and thus the parent is responsible for
17:58:25 ' 236 their deletion. When a <classname>qt:object</classname> has a parent, a strong
2009-06-04 tobias 237 reference is kept to prevent the garbage collection removing it until the parent is deleted.
2009-04-05 tobias 238 </para>
2009-04-12 tobias 239 <caution>
2009-04-09 tobias 240 <para>
2009-08-30 tobias 241 Ownership transfer for non QObject instances is mostly unimplemented.
2009-06-04 tobias 242 </para>
21:20:49 ' 243 </caution>
2009-04-05 tobias 244 </section>
2009-05-19 tobias 245
2009-05-14 tobias 246 <section id="core-image"><title>Saving a Core Image</title>
12:56:16 ' 247 <para>
2009-05-19 tobias 248 For near instant startup you can save an image. Since saving C++ instances is not supported,
14:44:30 ' 249 it is best to save the image immediately after loading the packages.
2009-05-14 tobias 250 </para>
2009-05-19 tobias 251
14:44:30 ' 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
2009-05-14 tobias 262 <section><title>Bundle</title>
12:56:16 ' 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>
2009-04-05 tobias 272
2009-05-19 tobias 273 <section><title>Clozure CL</title>
14:44:30 ' 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
2009-04-05 tobias 294 </chapter>