Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> |
2 | <html> | |
3 | <head> | |
4 | <title>SWIG and Ocaml</title> | |
5 | <link rel="stylesheet" type="text/css" href="style.css"> | |
6 | </head> | |
7 | <body bgcolor="#ffffff"> | |
8 | <a name="n1"></a> | |
9 | <H1><a name="Ocaml"></a>22 SWIG and Ocaml</H1> | |
10 | <!-- INDEX --> | |
11 | <div class="sectiontoc"> | |
12 | <ul> | |
13 | <li><a href="#Ocaml_nn2">Preliminaries</a> | |
14 | <ul> | |
15 | <li><a href="#Ocaml_nn3">Running SWIG</a> | |
16 | <li><a href="#Ocaml_nn4">Compiling the code</a> | |
17 | <li><a href="#Ocaml_nn5">The camlp4 module</a> | |
18 | <li><a href="#Ocaml_nn6">Using your module</a> | |
19 | <li><a href="#Ocaml_nn7">Compilation problems and compiling with C++</a> | |
20 | </ul> | |
21 | <li><a href="#Ocaml_nn8">The low-level Ocaml/C interface</a> | |
22 | <ul> | |
23 | <li><a href="#Ocaml_nn9">The generated module</a> | |
24 | <li><a href="#Ocaml_nn10">Enums</a> | |
25 | <ul> | |
26 | <li><a href="#Ocaml_nn11">Enum typing in Ocaml</a> | |
27 | </ul> | |
28 | <li><a href="#Ocaml_nn12">Arrays</a> | |
29 | <ul> | |
30 | <li><a href="#Ocaml_nn13">Simple types of bounded arrays</a> | |
31 | <li><a href="#Ocaml_nn14">Complex and unbounded arrays</a> | |
32 | <li><a href="#Ocaml_nn15">Using an object</a> | |
33 | <li><a href="#Ocaml_nn16">Example typemap for a function taking float * and int</a> | |
34 | </ul> | |
35 | <li><a href="#Ocaml_nn17">C++ Classes</a> | |
36 | <ul> | |
37 | <li><a href="#Ocaml_nn18">STL vector and string Example</a> | |
38 | <li><a href="#Ocaml_nn19">C++ Class Example</a> | |
39 | <li><a href="#Ocaml_nn20">Compiling the example</a> | |
40 | <li><a href="#Ocaml_nn21">Sample Session</a> | |
41 | </ul> | |
42 | <li><a href="#Ocaml_nn22">Director Classes</a> | |
43 | <ul> | |
44 | <li><a href="#Ocaml_nn23">Director Introduction</a> | |
45 | <li><a href="#Ocaml_nn24">Overriding Methods in Ocaml</a> | |
46 | <li><a href="#Ocaml_nn25">Director Usage Example</a> | |
47 | <li><a href="#Ocaml_nn26">Creating director objects</a> | |
48 | <li><a href="#Ocaml_nn27">Typemaps for directors, <tt>directorin, directorout, directorargout</tt></a> | |
49 | <li><a href="#Ocaml_nn28"><tt>directorin</tt> typemap</a> | |
50 | <li><a href="#Ocaml_nn29"><tt>directorout</tt> typemap</a> | |
51 | <li><a href="#Ocaml_nn30"><tt>directorargout</tt> typemap</a> | |
52 | </ul> | |
53 | <li><a href="#Ocaml_nn31">Exceptions</a> | |
54 | </ul> | |
55 | </ul> | |
56 | </div> | |
57 | <!-- INDEX --> | |
58 | ||
59 | ||
60 | ||
61 | <p> | |
62 | This chapter describes SWIG's | |
63 | support of Ocaml. Ocaml is a relatively recent addition to the ML family, | |
64 | and is a recent addition to SWIG. It's the second compiled, typed | |
65 | language to be added. Ocaml has widely acknowledged benefits for engineers, | |
66 | mostly derived from a sophistocated type system, compile-time checking | |
67 | which eliminates several classes of common programming errors, and good | |
68 | native performance. While all of this is wonderful, there are well-written | |
69 | C and C++ libraries that Ocaml users will want to take advantage of as | |
70 | part of their arsenal (such as SSL and gdbm), as well as their own mature | |
71 | C and C++ code. SWIG allows this code to be used in a natural, type-safe | |
72 | way with Ocaml, by providing the necessary, but repetetive glue code | |
73 | which creates and uses Ocaml values to communicate with C and C++ code. | |
74 | In addition, SWIG also produces the needed Ocaml source that binds | |
75 | variants, functions, classes, etc. | |
76 | </p> | |
77 | ||
78 | <p> | |
79 | If you're not familiar with the Objective Caml language, you can visit | |
80 | <a href="http://www.ocaml.org/">The Ocaml Website</a>. | |
81 | </p> | |
82 | ||
83 | <H2><a name="Ocaml_nn2"></a>22.1 Preliminaries</H2> | |
84 | ||
85 | ||
86 | <p> | |
87 | SWIG 1.3 works with Ocaml 3.04 and above. Given the choice, | |
88 | you should use the latest stable release. The SWIG Ocaml module has | |
89 | been tested on Linux (x86,PPC,Sparc) and Cygwin on Windows. The | |
90 | best way to determine whether your system will work is to compile the | |
91 | examples and test-suite which come with SWIG. You can do this by running | |
92 | <tt>make check</tt> from the SWIG root directory after installing SWIG. | |
93 | The Ocaml module has been tested using the system's dynamic linking (the | |
94 | usual -lxxx against libxxx.so, as well as with Gerd Stolpmann's | |
95 | <a | |
96 | href="http://www.ocaml-programming.de/packages/documentation/dl/">Dl package | |
97 | </a>. The ocaml_dynamic and ocaml_dynamic_cpp targets in the | |
98 | file Examples/Makefile illustrate how to compile and link SWIG modules that | |
99 | will be loaded dynamically. This has only been tested on Linux so far. | |
100 | </p> | |
101 | ||
102 | <H3><a name="Ocaml_nn3"></a>22.1.1 Running SWIG</H3> | |
103 | ||
104 | ||
105 | <p> | |
106 | The basics of getting a SWIG Ocaml module up and running | |
107 | can be seen from one of SWIG's example Makefiles, but is also described | |
108 | here. To build an Ocaml module, run SWIG using the <tt>-ocaml</tt> | |
109 | option. | |
110 | </p> | |
111 | ||
112 | <div class="code"> | |
113 | <pre> | |
114 | %swig -ocaml example.i | |
115 | </pre> | |
116 | </div> | |
117 | ||
118 | <p> This will produce 3 files. The file <tt>example_wrap.c</tt> contains | |
119 | all of the C code needed to build an Ocaml module. To build the module, | |
120 | you will compile the file <tt>example_wrap.c</tt> with <tt>ocamlc</tt> or | |
121 | <tt>ocamlopt</tt> to create the needed .o file. You will need to compile | |
122 | the resulting .ml and .mli files as well, and do the final link with -custom | |
123 | (not needed for native link). </p> | |
124 | ||
125 | <H3><a name="Ocaml_nn4"></a>22.1.2 Compiling the code</H3> | |
126 | ||
127 | ||
128 | <p> | |
129 | The O'Caml SWIG module now requires you to compile a module (<tt>Swig</tt>) | |
130 | separately. In addition to aggregating common SWIG functionality, the Swig | |
131 | module contains the data structure that represents C/C++ values. This allows | |
132 | easier data sharing between modules if two or more are combined, because | |
133 | the type of each SWIG'ed module's c_obj is derived from Swig.c_obj_t. This | |
134 | also allows SWIG to acquire new conversions painlessly, as well as giving | |
135 | the user more freedom with respect to custom typing. | |
136 | ||
137 | Use <tt>ocamlc</tt> or <tt>ocamlopt</tt> to compile your | |
138 | SWIG interface like: | |
139 | </p> | |
140 | ||
141 | <div class="code"> | |
142 | <pre> | |
143 | % swig -ocaml -co swig.mli ; swig -ocaml co swig.ml | |
144 | % ocamlc -c swig.mli ; ocamlc -c swig.ml | |
145 | % ocamlc -c -ccopt "-I/usr/include/foo" example_wrap.c | |
146 | % ocamlc -c example.mli | |
147 | % ocamlc -c example.ml | |
148 | </pre> | |
149 | </div> | |
150 | ||
151 | <p> <tt>ocamlc</tt> is aware of .c files and knows how to handle them. Unfortunately, | |
152 | it does not know about .cxx, .cc, or .cpp files, so when SWIG is invoked | |
153 | in C++ mode, you must: </p> | |
154 | ||
155 | <div class="code"> | |
156 | <pre> | |
157 | % cp example_wrap.cxx example_wrap.cxx.c<br>% ocamlc -c ... -ccopt -xc++ example_wrap.cxx.c<br>% ...<br> | |
158 | </pre> | |
159 | </div> | |
160 | ||
161 | <H3><a name="Ocaml_nn5"></a>22.1.3 The camlp4 module</H3> | |
162 | ||
163 | ||
164 | <p> | |
165 | The camlp4 module (swigp4.ml -> swigp4.cmo) contains a simple rewriter which | |
166 | makes C++ code blend more seamlessly with objective caml code. It's use is | |
167 | optional, but encouraged. The source file is included in the Lib/ocaml | |
168 | directory of the SWIG source distribution. You can checkout this file with | |
169 | <tt>"swig -ocaml -co swigp4.ml"</tt>. You should compile the file with | |
170 | <tt>"ocamlc -I `camlp4 -where` -pp 'camlp4o pa_extend.cmo q_MLast.cmo' -c swigp4.ml"</tt> | |
171 | </p> | |
172 | ||
173 | <p> | |
174 | The basic principle of the module is to recognize certain non-caml expressions | |
175 | and convert them for use with C++ code as interfaced by SWIG. The camlp4 | |
176 | module is written to work with generated SWIG interfaces, and probably isn't | |
177 | great to use with anything else. | |
178 | </p> | |
179 | ||
180 | <p> | |
181 | Here are the main rewriting rules: | |
182 | </p> | |
183 | ||
184 | <table border="1" summary="Rewriting rules"> | |
185 | <tr><th>Input</th><th>Rewritten to</th></tr> | |
186 | <tr><td>f'( ... ) as in<br> atoi'("0") or<br> _exit'(0)</td> | |
187 | <td>f(C_list [ ... ]) as in<br> atoi (C_list [ C_string "0" ]) or<br> _exit (C_list [ C_int 0 ])</td></tr> | |
188 | <tr><td>object -> method ( ... )</td><td>(invoke object) "method" (C_list [ ... ])</td></tr> | |
189 | <tr><td> | |
190 | object <i>'binop</i> argument as in<br> | |
191 | a '+= b</td> | |
192 | <td> | |
193 | (invoke object) "+=" argument as in<br> | |
194 | (invoke a) "+=" b<td></tr> | |
195 | <tr><th colspan=2>Note that because camlp4 always recognizes << | |
196 | and >>, they are replaced by lsl and lsr in operator names. | |
197 | <tr><td> | |
198 | <i>'unop</i> object as in<br> | |
199 | '! a | |
200 | </td><td> | |
201 | (invoke a) "!" C_void</td></tr> | |
202 | <tr><td> | |
203 | <b>Smart pointer access like this</b><br> | |
204 | object '-> method ( args )<br> | |
205 | </td><td> | |
206 | (invoke (invoke object "->" C_void)) | |
207 | </td></tr> | |
208 | <tr><td> | |
209 | <b>Invoke syntax</b><br> | |
210 | object . '( ... ) | |
211 | </td><td> | |
212 | (invoke object) "()" (C_list [ ... ]) | |
213 | </td></tr> | |
214 | <tr><td> | |
215 | <b>Array syntax</b><br> | |
216 | object '[ 10 ] | |
217 | </td><td> | |
218 | (invoke object) "[]" (C_int 10) | |
219 | </td></tr> | |
220 | <tr><td> | |
221 | <b>Assignment syntax</b><br> | |
222 | let a = '10 and b = '"foo" and c = '1.0 and d = 'true | |
223 | </td><td> | |
224 | let a = C_int 10 and b = C_string "foo" and c = C_double 1.0 and d = C_bool true | |
225 | </td></tr> | |
226 | <tr><td> | |
227 | <b>Cast syntax</b><br> | |
228 | let a = _atoi '("2") as int<br> | |
229 | let b = (getenv "PATH") to string<br> | |
230 | This works for int, string, float, bool | |
231 | </td><td> | |
232 | let a = get_int (_atoi (C_string "2"))<br> | |
233 | let b = C_string (getenv "PATH") | |
234 | </td></tr> | |
235 | </table> | |
236 | ||
237 | <H3><a name="Ocaml_nn6"></a>22.1.4 Using your module</H3> | |
238 | ||
239 | ||
240 | <p> | |
241 | You can test-drive your module by building a | |
242 | toplevel ocaml interpreter. Consult the ocaml manual for details. | |
243 | </p> | |
244 | ||
245 | <p> | |
246 | When linking any ocaml bytecode with your module, use the -custom | |
247 | option to build your functions into the primitive list. This | |
248 | option is not needed when you build native code. | |
249 | </p> | |
250 | ||
251 | <H3><a name="Ocaml_nn7"></a>22.1.5 Compilation problems and compiling with C++</H3> | |
252 | ||
253 | ||
254 | <p> | |
255 | As mentioned above, .cxx files need special | |
256 | handling to be compiled with <tt>ocamlc</tt>. Other than that, C code | |
257 | that uses <tt>class</tt> as a non-keyword, and C code that is too | |
258 | liberal with pointer types may not compile under the C++ compiler. | |
259 | Most code meant to be compiled as C++ will not have problems. | |
260 | </p> | |
261 | ||
262 | <H2><a name="Ocaml_nn8"></a>22.2 The low-level Ocaml/C interface</H2> | |
263 | ||
264 | ||
265 | <p> | |
266 | In order to provide access to overloaded functions, and | |
267 | provide sensible outputs from them, all C entites are represented as | |
268 | members of the c_obj type: | |
269 | </p> | |
270 | ||
271 | <p> | |
272 | In the code as seen by the typemap | |
273 | writer, there is a value, swig_result, that always contains the | |
274 | current return data. It is a list, and must be appended with the | |
275 | caml_list_append function, or with functions and macros provided by | |
276 | objective caml.<br> | |
277 | </p> | |
278 | ||
279 | <div class="code"><pre> | |
280 | type c_obj = | |
281 | C_void | |
282 | | C_bool of bool | |
283 | | C_char of char | |
284 | | C_uchar of char | |
285 | | C_short of int | |
286 | | C_ushort of int | |
287 | | C_int of int | |
288 | | C_uint of int32 | |
289 | | C_int32 of int32 | |
290 | | C_int64 of int64 | |
291 | | C_float of float | |
292 | | C_double of float | |
293 | | C_ptr of int64 * int64 | |
294 | | C_array of c_obj array | |
295 | | C_list of c_obj list | |
296 | | C_obj of (string -> c_obj -> c_obj) | |
297 | | C_string of string | |
298 | | C_enum of c_enum_t | |
299 | </pre></div> | |
300 | ||
301 | <p> | |
302 | A few functions exist which generate and return these: | |
303 | </p> | |
304 | ||
305 | <ul> | |
306 | <li>caml_ptr_val receives a c_obj and returns a void *. This | |
307 | should be used for all pointer purposes.</li> | |
308 | <li>caml_long_val receives a c_obj and returns a long. This | |
309 | should be used for most integral purposes.<br> | |
310 | </li> | |
311 | <li>caml_val_ptr receives a void * and returns a c_obj.</li> | |
312 | <li>caml_val_bool receives a C int and returns a c_obj representing | |
313 | it's bool value.</li> | |
314 | <li>caml_val_(u)?(char|short|int|long|float|double) receives an | |
315 | appropriate C value and returns a c_obj representing it.</li> | |
316 | <li>caml_val_string receives a char * and returns a string value.</li> | |
317 | <li>caml_val_string_len receives a char * and a length and returns | |
318 | a string value.</li> | |
319 | <li>caml_val_obj receives a void * and an object type and returns | |
320 | a C_obj, which contains a closure giving method access.</li> | |
321 | ||
322 | </ul> | |
323 | ||
324 | <p> | |
325 | Because of this style, a typemap can return any kind of value it | |
326 | wants from a function. This enables out typemaps and inout typemaps | |
327 | to work well. The one thing to remember about outputting values | |
328 | is that you must append them to the return list with swig_result = caml_list_append(swig_result,v). | |
329 | </p> | |
330 | ||
331 | <p> | |
332 | This function will return a new list that has your element | |
333 | appended. Upon return to caml space, the fnhelper function | |
334 | beautifies the result. A list containing a single item degrades to | |
335 | only that item (i.e. [ C_int 3 ] -> C_int 3), and a list | |
336 | containing more than one item is wrapped in C_list (i.e. [ C_char | |
337 | 'a' ; C_char 'b' -> C_list [ C_char 'a' ; C_char b | |
338 | ]). This is in order to make return values easier to handle | |
339 | when functions have only one return value, such as constructors, | |
340 | and operators. In addition, string, pointer, and object | |
341 | values are interchangable with respect to caml_ptr_val, so you can | |
342 | allocate memory as caml strings and still use the resulting | |
343 | pointers for C purposes, even using them to construct simple objects | |
344 | on. Note, though, that foreign C++ code does not respect the garbage | |
345 | collector, although the SWIG interface does.</p> | |
346 | ||
347 | <p> | |
348 | The wild card type that you can use in lots of different ways is | |
349 | C_obj. It allows you to wrap any type of thing you like as an | |
350 | object using the same mechanism that the ocaml module | |
351 | does. When evaluated in caml_ptr_val, the returned value is | |
352 | the result of a call to the object's "&" operator, taken as a pointer. | |
353 | </p> | |
354 | <p> | |
355 | You should only construct values using objective caml, or using the | |
356 | functions caml_val_* functions provided as static functions to a SWIG | |
357 | ocaml module, as well as the caml_list_* functions. These functions | |
358 | provide everything a typemap needs to produce values. In addition, | |
359 | value items pass through directly, but you must make your own type | |
360 | signature for a function that uses value in this way. | |
361 | </p> | |
362 | ||
363 | <H3><a name="Ocaml_nn9"></a>22.2.1 The generated module</H3> | |
364 | ||
365 | ||
366 | <p> | |
367 | The SWIG <tt>%module</tt> directive specifies the name of the Ocaml | |
368 | module to be generated. If you specified `<tt>%module example</tt>', | |
369 | then your Ocaml code will be accessible in the module Example. The | |
370 | module name is always capitalized as is the ocaml convention. Note | |
371 | that you must not use any Ocaml keyword to name your module. Remember | |
372 | that the keywords are not the same as the C++ ones. | |
373 | </p> | |
374 | ||
375 | <p> | |
376 | You can introduce extra code into the output wherever you like with SWIG. | |
377 | These are the places you can introduce code: | |
378 | <table border="1" summary="Extra code sections"> | |
379 | <tr><td>"header"</td><td>This code is inserted near the beginning of the | |
380 | C wrapper file, before any function definitions.</td></tr> | |
381 | <tr><td>"wrapper"</td><td>This code is inserted in the function definition | |
382 | section.</td></tr> | |
383 | <tr><td>"runtime"</td><td>This code is inserted near the end of the C wrapper | |
384 | file.</td></tr> | |
385 | <tr><td>"mli"</td><td>This code is inserted into the caml interface file. | |
386 | Special signatures should be inserted here. | |
387 | </td></tr> | |
388 | <tr><td>"ml"</td><td>This code is inserted in the caml code defining the | |
389 | interface to your C code. Special caml code, as well as any initialization | |
390 | which should run when the module is loaded may be inserted here. | |
391 | </td></tr> | |
392 | <tr><td>"classtemplate"</td><td>The "classtemplate" place is special because | |
393 | it describes the output SWIG will generate for class definitions. | |
394 | </td></tr> | |
395 | </table> | |
396 | ||
397 | <H3><a name="Ocaml_nn10"></a>22.2.2 Enums</H3> | |
398 | ||
399 | ||
400 | <p> | |
401 | SWIG will wrap enumerations as polymorphic variants in the output | |
402 | Ocaml code, as above in C_enum. In order to support all | |
403 | C++-style uses of enums, the function int_to_enum and enum_to_int are | |
404 | provided for ocaml code to produce and consume these values as | |
405 | integers. Other than that, correct uses of enums will not have | |
406 | a problem. Since enum labels may overlap between enums, the | |
407 | enum_to_int and int_to_enum functions take an enum type label as an | |
408 | argument. Example: | |
409 | </p> | |
410 | ||
411 | <div class="code"><pre> | |
412 | %module enum_test | |
413 | %{ | |
414 | enum c_enum_type { a = 1, b, c = 4, d = 8 }; | |
415 | %} | |
416 | enum c_enum_type { a = 1, b, c = 4, d = 8 }; | |
417 | </pre></div> | |
418 | ||
419 | <p> | |
420 | The output mli contains: | |
421 | </p> | |
422 | ||
423 | <div class="code"><pre> | |
424 | type c_enum_type = [ | |
425 | `unknown | |
426 | | `c_enum_type | |
427 | ] | |
428 | type c_enum_tag = [ | |
429 | `int of int | |
430 | | `a | |
431 | | `b | |
432 | | `c | |
433 | | `d | |
434 | ] | |
435 | val int_to_enum c_enum_type -> int -> c_obj | |
436 | val enum_to_int c_enum_type -> c_obj -> c_obj | |
437 | </pre> | |
438 | </div> | |
439 | ||
440 | <p> | |
441 | So it's possible to do this: | |
442 | </p> | |
443 | ||
444 | <div class="code"> | |
445 | <pre> | |
446 | bash-2.05a$ ocamlmktop -custom enum_test_wrap.o enum_test.cmo -o enum_test_top | |
447 | bash-2.05a$ ./enum_test_top | |
448 | Objective Caml version 3.04 | |
449 | ||
450 | # open Enum_test ;; | |
451 | # let x = C_enum `a ;; | |
452 | val x : Enum_test.c_obj = C_enum `a | |
453 | # enum_to_int `c_enum_type x ;; | |
454 | - : Enum_test.c_obj = C_int 1 | |
455 | # int_to_enum `c_enum_type 4 ;; | |
456 | - : Enum_test.c_obj = C_enum `c | |
457 | </pre> | |
458 | </div> | |
459 | ||
460 | <H4><a name="Ocaml_nn11"></a>22.2.2.1 Enum typing in Ocaml</H4> | |
461 | ||
462 | ||
463 | <p> | |
464 | The ocaml SWIG module now has support for loading and using multiple SWIG | |
465 | modules at the same time. This enhances modularity, but presents problems | |
466 | when used with a language which assumes that each module's types are complete | |
467 | at compile time. In order to achieve total soundness enum types are now | |
468 | isolated per-module. The type issue matters when values are shared between | |
469 | functions imported from different modules. You must convert values to master | |
470 | values using the swig_val function before sharing them with another module. | |
471 | </p> | |
472 | ||
473 | <H3><a name="Ocaml_nn12"></a>22.2.3 Arrays</H3> | |
474 | ||
475 | ||
476 | <H4><a name="Ocaml_nn13"></a>22.2.3.1 Simple types of bounded arrays</H4> | |
477 | ||
478 | ||
479 | <p> | |
480 | SWIG has support for array types, but you generally will need to provide | |
481 | a typemap to handle them. You can currently roll your own, or expand | |
482 | some of the macros provided (but not included by default) with the SWIG | |
483 | distribution. | |
484 | </p> | |
485 | ||
486 | <p> | |
487 | By including "carray.i", you will get access to some macros that help you | |
488 | create typemaps for array types fairly easily. | |
489 | </p> | |
490 | ||
491 | <p> | |
492 | <tt>%make_simple_array_typemap</tt> is the easiest way to get access to | |
493 | arrays of simple types with known bounds in your code, but this only works | |
494 | for arrays whose bounds are completely specified. | |
495 | </p> | |
496 | ||
497 | <H4><a name="Ocaml_nn14"></a>22.2.3.2 Complex and unbounded arrays</H4> | |
498 | ||
499 | ||
500 | <p> | |
501 | Unfortunately, unbounded arrays and pointers can't be handled in a | |
502 | completely general way by SWIG, because the end-condition of such an | |
503 | array can't be predicted. In some cases, it will be by consent | |
504 | (e.g. an array of four or more chars), sometimes by explicit length | |
505 | (char *buffer, int len), and sometimes by sentinel value (0,-1,etc.). | |
506 | SWIG can't predict which of these methods will be used in the array, | |
507 | so you have to specify it for yourself in the form of a typemap. | |
508 | </p> | |
509 | ||
510 | <H4><a name="Ocaml_nn15"></a>22.2.3.3 Using an object</H4> | |
511 | ||
512 | ||
513 | <p> | |
514 | It's possible to use C++ to your advantage by creating a simple object that | |
515 | provides access to your array. This may be more desirable in some cases, | |
516 | since the object can provide bounds checking, etc., that prevents crashes. | |
517 | </p> | |
518 | ||
519 | <p> | |
520 | Consider writing an object when the ending condition of your array is complex, | |
521 | such as using a required centinel, etc. | |
522 | </p> | |
523 | ||
524 | <H4><a name="Ocaml_nn16"></a>22.2.3.4 Example typemap for a function taking float * and int</H4> | |
525 | ||
526 | ||
527 | <p> | |
528 | This is a simple example <tt>in</tt> typemap for an array of float, where the | |
529 | length of the array is specified as an extra parameter. Other such typemaps | |
530 | will work similarly. In the example, the function printfloats is called with | |
531 | a float array, and specified length. The actual length reported in the len | |
532 | argument is the length of the array passed from ocaml, making passing an array | |
533 | into this type of function convenient. | |
534 | </p> | |
535 | ||
536 | <table border="1" bgcolor="#dddddd" summary="float * and int typemap example"> | |
537 | <tr><th><center>tarray.i</center></th></tr> | |
538 | <tr><td><pre> | |
539 | %module tarray | |
540 | %{ | |
541 | #include <stdio.h> | |
542 | ||
543 | void printfloats( float *tab, int len ) { | |
544 | int i; | |
545 | ||
546 | for( i = 0; i < len; i++ ) { | |
547 | printf( "%f ", tab[i] ); | |
548 | } | |
549 | ||
550 | printf( "\n" ); | |
551 | } | |
552 | %} | |
553 | ||
554 | %typemap(in) (float *tab, int len) { | |
555 | int i; | |
556 | /* $*1_type */ | |
557 | $2 = caml_array_len($input); | |
558 | $1 = ($*1_type *)malloc( $2 * sizeof( float ) ); | |
559 | for( i = 0; i < $2; i++ ) { | |
560 | $1[i] = caml_double_val(caml_array_nth($input,i)); | |
561 | } | |
562 | } | |
563 | ||
564 | void printfloats( float *tab, int len ); | |
565 | </pre></td></tr> | |
566 | <tr><th>Sample Run</th></tr> | |
567 | <tr><td><pre> | |
568 | # open Tarray ;; | |
569 | # _printfloats (C_array [| C_double 1.0 ; C_double 3.0 ; C_double 5.6666 |]) ;; | |
570 | 1.000000 3.000000 5.666600 | |
571 | - : Tarray.c_obj = C_void | |
572 | </pre></td></tr></table> | |
573 | ||
574 | ||
575 | <H3><a name="Ocaml_nn17"></a>22.2.4 C++ Classes</H3> | |
576 | ||
577 | ||
578 | <p> | |
579 | C++ classes, along with structs and unions are represented by C_obj | |
580 | (string -> c_obj -> c_obj) wrapped closures. These objects | |
581 | contain a method list, and a type, which allow them to be used like | |
582 | C++ objects. When passed into typemaps that use pointers, they | |
583 | degrade to pointers through their "&" method. Every method | |
584 | an object has is represented as a string in the object's method table, | |
585 | and each method table exists in memory only once. In addition | |
586 | to any other operators an object might have, certain builtin ones are | |
587 | provided by SWIG: (all of these take no arguments (C_void)) | |
588 | </p> | |
589 | ||
590 | <table summary="SWIG provided operators"> | |
591 | <tr><td>"~"</td><td>Delete this object</td></tr> | |
592 | <tr><td>"&"</td><td>Return an ordinary C_ptr value representing this | |
593 | object's address</td></tr> | |
594 | <tr><td>"sizeof"</td><td>If enabled with ("sizeof"="1") on the module node, | |
595 | return the object's size in char.</td></tr> | |
596 | <tr><td>":methods"</td><td>Returns a list of strings containing the names of | |
597 | the methods this object contains</td></tr> | |
598 | <tr><td>":classof"</td><td>Returns the name of the class this object belongs | |
599 | to.</td></tr> | |
600 | <tr><td>":parents"</td><td>Returns a list of all direct parent classes which | |
601 | have been wrapped by SWIG.</td></tr> | |
602 | <tr><td>"::[parent-class]"</td><td>Returns a view of the object as the | |
603 | indicated parent class. This is mainly used internally by the SWIG module, | |
604 | but may be useful to client programs.</td></tr> | |
605 | <tr><td>"[member-variable]"</td><td>Each member variable is wrapped as a | |
606 | method with an optional parameter. | |
607 | Called with one argument, the member variable is set to the value of the | |
608 | argument. With zero arguments, the value is returned. | |
609 | </td></tr> | |
610 | </table> | |
611 | ||
612 | <p> | |
613 | Note that this string belongs to the wrapper object, and not | |
614 | the underlying pointer, so using create_[x]_from_ptr alters the | |
615 | returned value for the same object. | |
616 | </p> | |
617 | ||
618 | <H4><a name="Ocaml_nn18"></a>22.2.4.1 STL vector and string Example</H4> | |
619 | ||
620 | ||
621 | <p> | |
622 | Standard typemaps are now provided for STL vector and string. More are in | |
623 | the works. STL strings are passed just like normal strings, and returned | |
624 | as strings. STL string references don't mutate the original string, (which | |
625 | might be surprising), because Ocaml strings are mutable but have fixed | |
626 | length. Instead, use multiple returns, as in the argout_ref example. | |
627 | </p> | |
628 | ||
629 | <table border="1" bgcolor="#dddddd" summary="STL vector and string example"> | |
630 | <tr><th><center>example.i</center></th></tr> | |
631 | <tr><td><pre> | |
632 | %module example | |
633 | %{ | |
634 | #include "example.h" | |
635 | %} | |
636 | ||
637 | %include stl.i | |
638 | ||
639 | namespace std { | |
640 | %template(StringVector) std::vector < string >; | |
641 | }; | |
642 | ||
643 | %include example.h | |
644 | </pre></td></tr> | |
645 | <tr><td><font size="-1"><i>This example is in Examples/ocaml/stl | |
646 | </i></font></td></tr> | |
647 | </table> | |
648 | ||
649 | <p> | |
650 | Since there's a makefile in that directory, the example is easy to build. | |
651 | </p> | |
652 | ||
653 | <p> | |
654 | Here's a sample transcript of an interactive session using a string vector | |
655 | after making a toplevel (make toplevel). This example uses the camlp4 | |
656 | module. | |
657 | </p> | |
658 | ||
659 | <div class="code"><pre> | |
660 | bash-2.05a$ ./example_top | |
661 | Objective Caml version 3.06 | |
662 | ||
663 | Camlp4 Parsing version 3.06 | |
664 | ||
665 | # open Swig ;; | |
666 | # open Example ;; | |
667 | # let x = new_StringVector '() ;; | |
668 | val x : Example.c_obj = C_obj <fun> | |
669 | # x -> ":methods" () ;; | |
670 | - : Example.c_obj = | |
671 | C_list | |
672 | [C_string "nop"; C_string "size"; C_string "empty"; C_string "clear"; | |
673 | C_string "push_back"; C_string "[]"; C_string "="; C_string "set"; | |
674 | C_string "~"; C_string "&"; C_string ":parents"; C_string ":classof"; | |
675 | C_string ":methods"] | |
676 | # x -> push_back ("foo") ;; | |
677 | - : Example.c_obj = C_void | |
678 | # x -> push_back ("bar") ;; | |
679 | - : Example.c_obj = C_void | |
680 | # x -> push_back ("baz") ;; | |
681 | - : Example.c_obj = C_void | |
682 | # x '[1] ;; | |
683 | - : Example.c_obj = C_string "bar" | |
684 | # x -> set (1,"spam") ;; | |
685 | - : Example.c_obj = C_void | |
686 | # x '[1] ;; | |
687 | - : Example.c_obj = C_string "spam" | |
688 | # for i = 0 to (x -> size() as int) - 1 do | |
689 | print_endline ((x '[i to int]) as string) | |
690 | done ;; | |
691 | foo | |
692 | bar | |
693 | baz | |
694 | - : unit = () | |
695 | # | |
696 | </pre></div> | |
697 | ||
698 | <H4><a name="Ocaml_nn19"></a>22.2.4.2 C++ Class Example</H4> | |
699 | ||
700 | ||
701 | <p> | |
702 | Here's a simple example using Trolltech's Qt Library: | |
703 | </p> | |
704 | ||
705 | <table border="1" bgcolor="#dddddd" summary="Qt Library example"> | |
706 | <tr><th><center>qt.i</center></th></tr> | |
707 | <tr><td><pre> | |
708 | %module qt | |
709 | %{ | |
710 | #include <qapplication.h> | |
711 | #include <qpushbutton.h> | |
712 | %} | |
713 | class QApplication { | |
714 | public: | |
715 | QApplication( int argc, char **argv ); | |
716 | void setMainWidget( QWidget *widget ); | |
717 | void exec(); | |
718 | }; | |
719 | ||
720 | class QPushButton { | |
721 | public: | |
722 | QPushButton( char *str, QWidget *w ); | |
723 | void resize( int x, int y ); | |
724 | void show(); | |
725 | }; | |
726 | </pre></td></tr></table> | |
727 | ||
728 | <H4><a name="Ocaml_nn20"></a>22.2.4.3 Compiling the example</H4> | |
729 | ||
730 | ||
731 | <div class="code"><pre> | |
732 | bash-2.05a$ QTPATH=/your/qt/path | |
733 | bash-2.05a$ for file in swig.mli swig.ml swigp4.ml ; do swig -ocaml -co $file ; done | |
734 | bash-2.05a$ ocamlc -c swig.mli ; ocamlc -c swig.ml | |
735 | bash-2.05a$ ocamlc -I `camlp4 -where` -pp "camlp4o pa_extend.cmo q_MLast.cmo" -c swigp4.ml | |
736 | bash-2.05a$ swig -ocaml -c++ -I$QTPATH/include qt.i | |
737 | bash-2.05a$ mv qt_wrap.cxx qt_wrap.c | |
738 | bash-2.05a$ ocamlc -c -ccopt -xc++ -ccopt -g -g -ccopt -I$QTPATH/include qt_wrap.c | |
739 | bash-2.05a$ ocamlc -c qt.mli | |
740 | bash-2.05a$ ocamlc -c qt.ml | |
741 | bash-2.05a$ ocamlmktop -custom swig.cmo -I `camlp4 -where` \ | |
742 | camlp4o.cma swigp4.cmo qt_wrap.o qt.cmo -o qt_top -cclib \ | |
743 | -L$QTPATH/lib -cclib -lqt | |
744 | </pre></div> | |
745 | ||
746 | <H4><a name="Ocaml_nn21"></a>22.2.4.4 Sample Session</H4> | |
747 | ||
748 | ||
749 | <div class="code"><pre> | |
750 | bash-2.05a$ ./qt_top | |
751 | Objective Caml version 3.06 | |
752 | ||
753 | Camlp4 Parsing version 3.06 | |
754 | ||
755 | # open Swig ;; | |
756 | # open Qt ;; | |
757 | # let a = new_QApplication '(0,0) ;; | |
758 | val a : Qt.c_obj = C_obj <fun> | |
759 | # let hello = new_QPushButton '("hi",0) ;; | |
760 | val hello : Qt.c_obj = C_obj <fun> | |
761 | # hello -> resize (100,30) ;; | |
762 | - : Qt.c_obj = C_void | |
763 | # hello -> show () ;; | |
764 | - : Qt.c_obj = C_void | |
765 | # a -> exec () ;; | |
766 | </pre></div> | |
767 | ||
768 | <p> | |
769 | Assuming you have a working installation of QT, you will see a window | |
770 | containing the string "hi" in a button. | |
771 | </p> | |
772 | ||
773 | <H3><a name="Ocaml_nn22"></a>22.2.5 Director Classes</H3> | |
774 | ||
775 | ||
776 | <H4><a name="Ocaml_nn23"></a>22.2.5.1 Director Introduction</H4> | |
777 | ||
778 | ||
779 | <p> | |
780 | Director classes are classes which allow Ocaml code to override the public | |
781 | methods of a C++ object. This facility allows the user to use C++ libraries | |
782 | that require a derived class to provide application specific functionality in | |
783 | the context of an application or utility framework. | |
784 | </p> | |
785 | ||
786 | <p> | |
787 | You can turn on director classes by using an optional module argument like | |
788 | this: | |
789 | </p> | |
790 | ||
791 | <div class="code"><pre> | |
792 | %module(directors="1") | |
793 | ||
794 | ... | |
795 | ||
796 | // Turn on the director class for a specific class like this: | |
797 | %feature("director") | |
798 | class foo { | |
799 | ... | |
800 | }; | |
801 | </pre></div> | |
802 | ||
803 | <H4><a name="Ocaml_nn24"></a>22.2.5.2 Overriding Methods in Ocaml</H4> | |
804 | ||
805 | ||
806 | <p> | |
807 | Because the Ocaml language module treats C++ method calls as calls to a | |
808 | certain function, all you need to do is to define the function that will | |
809 | handle the method calls in terms of the public methods of the object, and | |
810 | any other relevant information. The function <tt>new_derived_object</tt> | |
811 | uses a stub class to call your methods in place of the ones provided by the | |
812 | underlying implemenation. The object you receive is the underlying object, | |
813 | so you are free to call any methods you want from within your derived method. | |
814 | Note that calls to the underlying object do not invoke Ocaml code. You need | |
815 | to handle that yourself. | |
816 | </p> | |
817 | ||
818 | <p> | |
819 | <tt>new_derived_object</tt> receives your function, the function that creates | |
820 | the underlying object, and any constructor arguments, and provides an | |
821 | object that you can use in any usual way. When C++ code calls one of the | |
822 | object's methods, the object invokes the Ocaml function as if it had been | |
823 | invoked from Ocaml, allowing any method definitions to override the C++ ones. | |
824 | </p> | |
825 | ||
826 | <p> | |
827 | In this example, I'll examine the objective caml code involved in providing | |
828 | an overloaded class. This example is contained in Examples/ocaml/shapes. | |
829 | </p> | |
830 | ||
831 | <H4><a name="Ocaml_nn25"></a>22.2.5.3 Director Usage Example</H4> | |
832 | ||
833 | ||
834 | <table border="1" bgcolor="#dddddd" summary="Director usage example"> | |
835 | <tr><th><center>example_prog.ml</center> | |
836 | </th></tr> | |
837 | <tr><td><pre> | |
838 | open Swig | |
839 | open Example | |
840 | ||
841 | ... | |
842 | ||
843 | let triangle_class pts ob meth args = | |
844 | match meth with | |
845 | "cover" -> | |
846 | (match args with | |
847 | C_list [ x_arg ; y_arg ] -> | |
848 | let xa = x_arg as float | |
849 | and ya = y_arg as float in | |
850 | (point_in_triangle pts xa ya) to bool | |
851 | | _ -> raise (Failure "cover needs two double arguments.")) | |
852 | | _ -> (invoke ob) meth args ;; | |
853 | ||
854 | let triangle = | |
855 | new_derived_object | |
856 | new_shape | |
857 | (triangle_class ((0.0,0.0),(0.5,1.0),(1.0,0.0))) | |
858 | '() ;; | |
859 | ||
860 | let _ = _draw_shape_coverage '(triangle, C_int 60, C_int 20) ;; | |
861 | </pre></td></tr> | |
862 | </table> | |
863 | ||
864 | <p> | |
865 | This is the meat of what you need to do. The actual "class" definition | |
866 | containing the overloaded method is defined in the function triangle_class. | |
867 | This is a lot like the class definitions emitted by SWIG, if you look at | |
868 | example.ml, which is generated when SWIG consumes example.i. Basically, | |
869 | you are given the arguments as a c_obj and the method name as a string, and | |
870 | you must intercept the method you are interested in and provide whatever | |
871 | return value you need. Bear in mind that the underlying C++ code needs the | |
872 | right return type, or an exception will be thrown. This exception will | |
873 | generally be Failure, or NotObject. You must call other ocaml methods that | |
874 | you rely on yourself. Due to the way directors are implemented, method | |
875 | calls on your object from with ocaml code will always invoke C++ methods | |
876 | even if they are overridden in ocaml. | |
877 | </p> | |
878 | ||
879 | <p> | |
880 | In the example, the draw_shape_coverage function plots the indicated number | |
881 | of points as either covered (<tt>x</tt>) or uncovered ( ) between | |
882 | 0 and 1 on the X and Y axes. Your shape implementation can provide any | |
883 | coverage map it likes, as long as it responds to the "cover" method call | |
884 | with a boolean return (the underlying method returns bool). This might allow | |
885 | a tricky shape implementation, such as a boolean combination, to be expressed | |
886 | in a more effortless style in ocaml, while leaving the "engine" part of the | |
887 | program in C++. | |
888 | </p> | |
889 | ||
890 | <H4><a name="Ocaml_nn26"></a>22.2.5.4 Creating director objects</H4> | |
891 | ||
892 | ||
893 | <p> | |
894 | The definition of the actual object triangle can be described this way: | |
895 | </p> | |
896 | ||
897 | <div class="code"><pre> | |
898 | let triangle = | |
899 | new_derived_object | |
900 | new_shape | |
901 | (triangle_class ((0.0,0.0),(0.5,1.0),(1.0,0.0))) | |
902 | '() | |
903 | </pre></div> | |
904 | ||
905 | <p> | |
906 | The first argument to <tt>new_derived_object</tt>, new_shape is the method | |
907 | which returns a shape instance. This function will be invoked with the | |
908 | third argument will be appended to the argument list [ C_void ]. In the | |
909 | example, the actual argument list is sent as (C_list [ C_void ; C_void ]). | |
910 | The augmented constructor for a director class needs the first argument | |
911 | to determine whether it is being constructed as a derived object, or as | |
912 | an object of the indicated type only (in this case <tt>shape</tt>). The | |
913 | Second argument is a closure that will be added to the final C_obj. | |
914 | </p> | |
915 | ||
916 | <p> | |
917 | The actual object passed to the self parameter of the director object will | |
918 | be a C_director_core, containing a c_obj option ref and a c_obj. The | |
919 | c_obj provided is the same object that will be returned from new_derived | |
920 | object, that is, the object exposing the overridden methods. The other part | |
921 | is an option ref that will have its value extracted before becoming the | |
922 | <tt>ob</tt> parameter of your class closure. This ref will contain | |
923 | <tt>None</tt> if the C++ object underlying is ever destroyed, and will | |
924 | consequently trigger an exception when any method is called on the object | |
925 | after that point (the actual raise is from an inner function used by | |
926 | new_derived_object, and throws NotObject). This prevents a deleted C++ | |
927 | object from causing a core dump, as long as the object is destroyed | |
928 | properly. | |
929 | </p> | |
930 | ||
931 | <H4><a name="Ocaml_nn27"></a>22.2.5.5 Typemaps for directors, <tt>directorin, directorout, directorargout</tt></H4> | |
932 | ||
933 | ||
934 | <p> | |
935 | Special typemaps exist for use with directors, the <tt>directorin, directorout, directorargout</tt> | |
936 | are used in place of <tt>in, out, argout</tt> typemaps, except that their | |
937 | direction is reversed. They provide for you to provide argout values, as | |
938 | well as a function return value in the same way you provide function arguments, | |
939 | and to receive arguments the same way you normally receive function returns. | |
940 | </p> | |
941 | ||
942 | <H4><a name="Ocaml_nn28"></a>22.2.5.6 <tt>directorin</tt> typemap</H4> | |
943 | ||
944 | ||
945 | <p> | |
946 | The <tt>directorin</tt> typemap is used when you will receive arguments from a call | |
947 | made by C++ code to you, therefore, values will be translated from C++ to | |
948 | ocaml. You must provide some valid C_obj value. This is the value your ocaml | |
949 | code receives when you are called. In general, a simple <tt>directorin</tt> typemap | |
950 | can use the same body as a simple <tt>out</tt> typemap. | |
951 | </p> | |
952 | ||
953 | <H4><a name="Ocaml_nn29"></a>22.2.5.7 <tt>directorout</tt> typemap</H4> | |
954 | ||
955 | ||
956 | <p> | |
957 | The <tt>directorout</tt> typemap is used when you will send an argument from your | |
958 | code back to the C++ caller. That is; directorout specifies a function return | |
959 | conversion. You can usually use the same body as an <tt>in</tt> typemap | |
960 | for the same type, except when there are special requirements for object | |
961 | ownership, etc. | |
962 | </p> | |
963 | ||
964 | <H4><a name="Ocaml_nn30"></a>22.2.5.8 <tt>directorargout</tt> typemap</H4> | |
965 | ||
966 | ||
967 | <p> | |
968 | C++ allows function arguments which are by pointer (*) and by reference (&) | |
969 | to receive a value from the called function, as well as sending one there. | |
970 | Sometimes, this is the main purpose of the argument given. <tt>directorargout</tt> | |
971 | typemaps allow your caml code to emulate this by specifying additional return | |
972 | values to be put into the output parameters. The SWIG ocaml module is a bit | |
973 | loose in order to make code eaiser to write. In this case, your return to | |
974 | the caller must be a list containing the normal function return first, followed | |
975 | by any argout values in order. These argout values will be taken from the | |
976 | list and assigned to the values to be returned to C++ through directorargout typemaps. | |
977 | In the event that you don't specify all of the necessary values, integral | |
978 | values will read zero, and struct or object returns have undefined results. | |
979 | </p> | |
980 | ||
981 | <H3><a name="Ocaml_nn31"></a>22.2.6 Exceptions</H3> | |
982 | ||
983 | ||
984 | <p> | |
985 | Catching exceptions is now supported using SWIG's %exception feature. A simple | |
986 | but not too useful example is provided by the throw_exception testcase in | |
987 | Examples/test-suite. You can provide your own exceptions, too. | |
988 | </p> | |
989 | ||
990 | </body> | |
991 | </html> |