interface.xml 12.1 KB
Newer Older
1
<?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>
2
3
4
<!DOCTYPE page [
  <!ENTITY rarr     "&#8594;"> <!-- rightwards arrow, U+2192 ISOnum -->
]>
5
<page name="manual_interfacewithocaml">
6
7
8
9
10
11

<title>Interfacing CDuce with OCaml</title>

<box title="Introduction" link="intro">

<p>
12
This page describes the CDuce/OCaml interface. This interface allows
13
the programmer to:
14
</p>
15
16
<ul>
<li>call OCaml functions from a CDuce module;</li>
17
<li>export a CDuce model as an OCaml module, by giving it an explicit OCaml signature.</li>
18
</ul>
19
20

<p>
21
The intended usages for the interface are:
22
</p>
23
24
<ul>
<li>Piggyback existing OCaml libraries, such as database, 
25
    network, GUI, data structures;</li>
26
27
28
29
<li>Use CDuce as an XML layer (input/output/transformation) for OCaml
    projects;</li>
<li>Develop fully mixed OCaml/CDuce projects.</li>
</ul>
30

31
32
<p>
To see how to build CDuce with support for the OCaml interface, 
33
see the <a href="INSTALL">INSTALL</a> file from the CDuce distribution.
34
35
36
37
38
39
40
41
42
</p>


</box>

<box title="Translating types" link="transl">

<p>
The heart of the interface is a mapping from OCaml types to CDuce
43
44
45
46
47
types. An OCaml type <code>%%t%%</code> is translated to a CDuce type
<code>T(%%t%%)</code>, which is meant to be isomorphic to <code>%%t%%</code>:
there is a canonical function <code>%%t%%</code> &rarr; <code>T(%%t%%)</code>
from OCaml values of type <code>%%t%%</code> to CDuce values of type
<code>T(%%t%%)</code>, and another canonical function <code>T(%%t%%)</code> &rarr; <code>%%t%%</code>.
48
</p>
49

50
51
<ul>
<li>
52
53
54
55
Basic OCaml types <code>char</code>, <code>int</code>, <code>string</code>,
<code>unit</code> are translated respectively to
<code>Byte = '\0;'--'\255;'</code>, <code>-1073741824 --
1073741823</code>, <code>Latin1 = [ Byte* ]</code>, <code>[] = `nil</code>.
56
</li>
57

58
59
60
61
<li>
Tuple types <code>%%t%%1 * ... * %%t%%n</code> are translated to nested CDuce
product types <code>(T(%%t%%1),(...,T(%%t%%n))...)</code>. A function type
<code>%%t%% -> %%s%%</code> is translated to <code>T(%%t%%) -> T(%%s%%)</code>.
62
Labels and optional labels on the argument of the arrow are discarded.
63
</li>
64

65
<li>
66
A list type <code>%%t%% list</code> is translated to an homogeneous
67
68
sequence type <code>[ T(%%t%%)* ]</code>. An array type
<code>%%t%% array</code> has the same translation.
69
</li>
70

71
72
73
74
<li>
A variant type with a declaration <code>A1 of %%t%%1 | ... | An of
%%t%%n</code> is translated to a type <code>(`A1,T(%%t%%1)) | ... |
(`An,T(%%t%%n))</code>. If a constructor <code>Ai</code> has no argument, the resulting
75
76
term is <code>`Ai</code>, not <code>(`Ai,[])</code>.
Polymorphic variant types are treated similarly.
77
</li>
78

79
80
81
82
83
<li>
A record type with a declaration <code>{ l1 : %%t%%1; ...; ln : %%t%%n
}</code> is translated to a closed record type <code>{| l1 = T(%%t%%1);
... ; ln = T(%%t%%n) |}</code>. Mutable fields are just copied.
</li>
84

85
<li>
86
87
88
Private variant and record types are treated correctly: the interface
never tries to generate OCaml values of these types, but it will happily
translate them to CDuce values.
89
</li>
90

91
92
93
<li>
A reference type <code>%%t%% ref</code> is translated to the CDuce
reference type <code>ref T(%%t%%)</code>. When converting a Caml reference
94
95
96
97
to CDuce, the operation (set,get) on the resulting reference refers
to the original reference. However, when converting a CDuce reference
to OCaml, the content of the reference is fetched (set), and a fresh
OCaml reference is created (copy semantics).
98
</li>
99

100
<li>
101
The type <code>Cduce_lib.Value.t</code> is translated to the CDuce
102
103
104
type <code>Any</code>. The corresponding translation functions are the
identity. This can be used to avoid multiple copies when translating
a complex value back and forth between CDuce and OCaml.
105
</li>
106

107
<li>
108
109
110
111
112
A <em>monomorphic</em> abstract type <code>t</code> is translated to
the CDuce type <code>!t</code>. This type just acts as a container for
values of the abstract type. CDuce never produces a value of this
type, and it cannot inspect the content of such a value (apart
from checking its type).
113
114
115
116
117
</li>
</ul>

<p>
The canonical translation is summarized in the following box:
118
</p>
119

120
121
122

<table border="1" style="align:middle">
<tr>
123
124
<th>OCaml type <tt><i>t</i></tt></th>
<th>CDuce type <tt>T(<i>t</i>)</tt></th>
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
</tr>
<tr><td><tt>char</tt></td><td><tt>Byte = '\0;'--'\255;'</tt></td></tr>
<tr><td><tt>int</tt></td><td><tt>-1073741824 -- 1073741823</tt></td></tr>
<tr><td><tt>string</tt></td><td><tt>Latin1 = [ Byte* ]</tt></td></tr>
<tr><td><tt>unit</tt></td><td><tt>[] = `nil</tt></td></tr>
<tr><td><tt>bool</tt></td><td><tt>Bool = `true | `false</tt></td></tr>

<tr><td><tt><i>t1</i> * ... * <i>tn</i></tt></td>
<td><tt>(T(<i>t1</i>),(...,T(<i>tn</i>))...)</tt></td></tr>

<tr><td><tt><i>t</i> -> <i>s</i></tt></td>
<td><tt>T(<i>t</i>) -> T(<i>s</i>)</tt></td></tr>

<tr><td><tt><i>t</i> list</tt></td>
<td><tt>[ T(<i>t</i>)* ]</tt></td></tr>

<tr><td><tt><i>t</i> array</tt></td>
<td><tt>[ T(<i>t</i>)* ]</tt></td></tr>

<tr><td><tt>A of <i>t</i> | B of <i>s</i> | C</tt></td>
<td><tt>(`A, T(<i>t</i>)) | (`B, T(<i>s</i>)) | `C</tt></td></tr>

<tr><td><tt>[ `A of <i>t</i> | `B of <i>s</i> | `C ]</tt></td>
<td><tt>(`A, T(<i>t</i>)) | (`B, T(<i>s</i>)) | `C</tt></td></tr>

<tr><td><tt>{ x : <i>t</i>; y : <i>s</i> }</tt></td>
<td><tt>{| x = T(<i>t</i>); y = T(<i>s</i>) |}</tt></td></tr>

<tr><td><tt><i>t</i> ref</tt></td>
<td><tt>ref T(<i>t</i>)</tt></td></tr>

<tr><td><tt>Cduce_lib.Value.t</tt></td><td><tt>Any</tt></td></tr>
</table>

159
<p>
160
161
162
163
164
Only monomorphic types are handled by the interface. It is allowed to
use polymorphic constructors as an intermediate, as long as the final
type to be translated in monomorphic. Recursive types, including
unguarded ones (option <code>-rectypes</code> of the OCaml compiler)
are accepted. In the following example:
165
166
</p>

167
168
169
170
171
172
173
<sample>
type 'a t = A of int | B of 'a t
type s = int t

type 'a u = A of ('a * 'a) u | B
type v = int u
</sample>
174
175

<p>
176
177
the type <code>s</code> can be translated, but the type <code>v</code>
can't, because its infinite unfolding is not a regular type.
178
</p>
179

180
<p>
181
OCaml object types are not supported.
182
</p>
183

184
185
186
187
188
<p>
Note that values are copied in depth (until reaching an abstract type,
a function types, etc...). In particular, translating an OCaml cyclic
values to CDuce will not terminate (well, with a stack overflow !).
</p>
189

190
191
192
193
194
195
196
197
198
199
</box>

<box title="Calling OCaml from CDuce" link="call_ocaml">

<p>
If an OCaml value has a type that can be translated, it is possible to
use it from CDuce (see the <a href="#link">How to compile and link</a> section for
more details).
</p>

200
<p>
201
In a CDuce module, you can write <code>external "M.f"</code>
202
to denote the result of translating the OCaml value <code>M.f</code>
203
to CDuce. Actually, you can simply write <code>M.f</code>.
204
</p>
205
206
207
208

<p>
If the value you want to use has a polymorphic type, you can make
the translation work by explicitly instantiating its type
209
variables with CDuce types. The syntax is <code>external { "M.f" t1
210
211
212
213
214
215
216
217
218
219
220
221
222
... tn }</code> where the <code>ti</code> are CDuce types. The type
variables are listed in the order they appear in a left-to-right
reading of the OCaml type. Example:
</p>

<sample>
let listmap = external { "List.map" Int String }
</sample>

<p>
will return a function of type <code>(Int -> String) -> ([Int*] -> [String*])</code>
</p>

223
224
</box>

225
<box title="Calling CDuce from OCaml" link="call_cduce">
226
227

<p>
228
229
230
231
232
233
We have seen in the section above how OCaml values can be used from a
CDuce module. It is also possible to use CDuce values from OCaml. To
do so, you must give an OCaml interface (.mli) for the CDuce module
(.cdo). The interface can define arbitrary types, and declare
monomorphic values. These values must be defined in the CDuce module
with a compatible type (subtype of the translation).
234
235
</p>

236
237
238
239
240
241
242
243
244
<p>
As an example, suppose you have this CDuce module (foo.cd):
</p>

<sample>
type s = (`A,int) | `B
let double (x : Latin1) : Latin1 = x @ x
let dump (x : s) : Latin1 = string_of x
</sample>
245

246
<p>
247
You can define an OCaml interface for it (foo.mli):
248
</p>
249

250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
<sample>
type t = A of int | B
val double: string -> string
val dump: t -> string
</sample>

<p>
When the foo.cdo module is compiled, CDuce will look for the foo.cmi
compiled interface (hence, you must first compile it yourself with
OCaml), and generate stub code, so as to define an OCaml module
<code>Foo</code> with the given interface. This module can then be
linked together with other "regular" OCaml modules, and used from them.
</p>

<p>
Notes:
</p>

<ul>
<li>
It is not mandatory to export all the values of the CDuce module in
the OCaml interface.
</li>
<li>
The types defined in the interface cannot (currently) be used
within the CDuce module.
</li>
</ul>

279
280
</box>

281
<box title="How to compile and link" link="link">
282
283

<p>
284
Here is the protocol to compile a single CDuce module:
285
286
287
288
289
290
291
292
293
</p>

<ul>
  <li>
    Create a <code>.cmi</code> from your OCaml file with 
    <code>ocamlc -c foo.mli</code>.
  </li>
  <li>
    Compile your CDuce file <code>cduce --compile foo.cd</code>. This command
294
295
296
    will create a CDuce bytecode file <code>foo.cdo</code>, which
    also contains the OCaml glue code to export CDuce values as OCaml
    ones, and to bind OCaml values used within the CDuce module.
297
298
  </li>
  <li>
299
    Compile the OCaml glue code 
300
    <code>ocamlfind ocamlc -c -package cduce -pp cdo2ml -impl foo.cdo</code>.
301
302
    The<code>cdo2ml</code> tool extracts the OCaml glue code from the
    CDuce bytecode file.
303
304
305
  </li>
</ul>

306
307
308
309
310
311
312
313
314
315
316
317
318
<p>
  You can then link the resulting OCaml module, maybe with other
  modules (either regular ones, or wrapping a CDuce module):
  <code>ocamlfind ocamlc -o {{...}} -package cduce -linkpkg foo.cmo {{...}}</code>.
  When the program is run, the CDuce bytecode file
  <code>foo.cdo</code> is looked in the <em>current directory</em>
  only, and loaded dynamically (with a checksum test).
</p>

<p>
  It might be preferable to include the CDuce bytecode directly into
  the OCaml glue code. You can do this by giving <code>cdo2ml</code>
  the <code>-static</code> option:
319
  <code>ocamlfind ocamlc -c -package cduce -pp "cdo2ml -static" -impl foo.cdo</code>.
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
  Modules which have been compiled this way don't need the
  corresponding <code>.cdo</code> at runtime.
</p>

<p>
  If you choose static linking, you have to use a correct ordering
  when linking with OCaml. Note that it is possible to mix static and
  dynamic linking for various CDuce modules in a same program.
</p>

<p>
  Everything works mutatis mutandis with the native OCaml compiler ocamlopt.
</p>

<p>
  You might need to pass extra <code>-I</code> flags to CDuce so that
  it could find the referenced <code>.cmi</code> files.
</p>

<p>
  It is possible to run a CDuce module with <code>cduce --run
341
  foo.cdo</code>, but only if it doesn't use OCaml values.
342
343
344
345
346
347
348
</p>

<p>
  Interested users can look at the output of <code>cdo2ml</code> to
  better understand how the interface works.
</p>

349
</box>
350
351
352
353
354
355

<box title="Examples" link="examples">

<section title="Getting the value of an environment variable">

<sample>
356
let home = Sys.getenv "home";;
357
358
359
360
361
362
363
364
365
366
367
</sample>

</section>

<section title="Ejecting your CD with CDuce">

<p>
This example demonstrates how to use OCamlSDL library.
</p>

<sample>
368
369
370
Sdl.init `None [ `EVERYTHING ];;
let cd = Sdlcdrom.cd_open 0;; 
Sdlcdrom.cd_eject cd;;
371
372
373
374
375
376
377
378
379
380
381
382
383
</sample>

<p>
If you put these lines in a file <code>cdsdl.cd</code>, you can
compile and link it with:
</p>

<sample>
cduce --compile cdsdl.cd -I `ocamlfind query ocamlsdl`
ocamlfind ocamlc -o cdsdl -pp "cdo2ml -static" -impl cdsdl.cdo -package cduce,ocamlsdl -linkpkg
</sample>


384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
</section>

<section title="Accessing MySQL">

<p>
This example demonstrates how to use ocaml-mysql library.
</p>

<sample>
let db = Mysql.connect Mysql.defaults;;

match Mysql.list_dbs db `None [] with
 | (`Some,l) -> print [ 'Databases: ' !(string_of l) '\n' ]
 | `None -> [];;

print [ 
  'Client info: ' !(Mysql.client_info []) '\n'
  'Host info: ' !(Mysql.host_info db) '\n'
  'Server info: ' !(Mysql.server_info db) '\n'
  'Proto info: ' !(string_of (Mysql.proto_info db)) '\n'
];;
</sample>

<p>
If you put these lines in a file <code>cdmysql.cd</code>, you can
compile and link it with:
</p>

<sample>
cduce --compile cdmysql.cd -I `ocamlfind query mysql`
ocamlfind ocamlc -o cdmysql -pp "cdo2ml -static" -impl cdmysql.cdo -package cduce,mysql -linkpkg
</sample>

417
418
419
420
</section>

</box>

421
</page>