Whitespace cleanup

This commit is contained in:
Olly Betts 2015-03-19 13:15:23 +13:00
commit 13894f803b

View file

@ -1,11 +1,11 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>SWIG and Ocaml</title>
<title>SWIG and Ocaml</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body bgcolor="#ffffff">
<a name="n1"></a>
<body bgcolor="#ffffff">
<H1><a name="Ocaml"></a>31 SWIG and Ocaml</H1>
<!-- INDEX -->
<div class="sectiontoc">
@ -59,20 +59,23 @@
<p>
This chapter describes SWIG's
support of Ocaml. Ocaml is a relatively recent addition to the ML family,
and is a recent addition to SWIG. It's the second compiled, typed
language to be added. Ocaml has widely acknowledged benefits for engineers,
mostly derived from a sophisticated type system, compile-time checking
which eliminates several classes of common programming errors, and good
native performance. While all of this is wonderful, there are well-written
C and C++ libraries that Ocaml users will want to take advantage of as
part of their arsenal (such as SSL and gdbm), as well as their own mature
C and C++ code. SWIG allows this code to be used in a natural, type-safe
way with Ocaml, by providing the necessary, but repetitive glue code
which creates and uses Ocaml values to communicate with C and C++ code.
In addition, SWIG also produces the needed Ocaml source that binds
variants, functions, classes, etc.
This chapter describes SWIG's support of Ocaml.
</p>
<p>
Ocaml is a relatively recent addition to the ML family,
and is a recent addition to SWIG. It's the second compiled, typed
language to be added. Ocaml has widely acknowledged benefits for engineers,
mostly derived from a sophisticated type system, compile-time checking
which eliminates several classes of common programming errors, and good
native performance. While all of this is wonderful, there are well-written
C and C++ libraries that Ocaml users will want to take advantage of as
part of their arsenal (such as SSL and gdbm), as well as their own mature
C and C++ code. SWIG allows this code to be used in a natural, type-safe
way with Ocaml, by providing the necessary, but repetitive glue code
which creates and uses Ocaml values to communicate with C and C++ code.
In addition, SWIG also produces the needed Ocaml source that binds
variants, functions, classes, etc.
</p>
<p>
@ -84,17 +87,16 @@ If you're not familiar with the Objective Caml language, you can visit
<p>
SWIG 3.0 works with Ocaml 3.08.3 and above. Given the choice,
you should use the latest stable release. The SWIG Ocaml module has
been tested on Linux (x86,PPC,Sparc) and Cygwin on Windows. The
best way to determine whether your system will work is to compile the
examples and test-suite which come with SWIG. You can do this by running
<tt>make check</tt> from the SWIG root directory after installing SWIG.
The Ocaml module has been tested using the system's dynamic linking (the
usual -lxxx against libxxx.so, as well as with Gerd Stolpmann's
<a
href="http://download.camlcity.org/download/">Dl package
</a>. The ocaml_dynamic and ocaml_dynamic_cpp targets in the
SWIG 3.0 works with Ocaml 3.08.3 and above. Given the choice,
you should use the latest stable release. The SWIG Ocaml module has
been tested on Linux (x86,PPC,Sparc) and Cygwin on Windows. The
best way to determine whether your system will work is to compile the
examples and test-suite which come with SWIG. You can do this by running
<tt>make check</tt> from the SWIG root directory after installing SWIG.
The Ocaml module has been tested using the system's dynamic linking (the
usual -lxxx against libxxx.so, as well as with Gerd Stolpmann's
<a href="http://download.camlcity.org/download/">Dl package</a>.
The ocaml_dynamic and ocaml_dynamic_cpp targets in the
file Examples/Makefile illustrate how to compile and link SWIG modules that
will be loaded dynamically. This has only been tested on Linux so far.
</p>
@ -103,30 +105,30 @@ will be loaded dynamically. This has only been tested on Linux so far.
<p>
The basics of getting a SWIG Ocaml module up and running
can be seen from one of SWIG's example Makefiles, but is also described
here. To build an Ocaml module, run SWIG using the <tt>-ocaml</tt>
option.
The basics of getting a SWIG Ocaml module up and running
can be seen from one of SWIG's example Makefiles, but is also described
here. To build an Ocaml module, run SWIG using the <tt>-ocaml</tt>
option.
</p>
<div class="code">
<pre>
<div class="code">
<pre>
%swig -ocaml example.i
</pre>
</pre>
</div>
<p> This will produce 3 files. The file <tt>example_wrap.c</tt> contains
<p>This will produce 3 files. The file <tt>example_wrap.c</tt> contains
all of the C code needed to build an Ocaml module. To build the module,
you will compile the file <tt>example_wrap.c</tt> with <tt>ocamlc</tt> or
you will compile the file <tt>example_wrap.c</tt> with <tt>ocamlc</tt> or
<tt>ocamlopt</tt> to create the needed .o file. You will need to compile
the resulting .ml and .mli files as well, and do the final link with -custom
(not needed for native link). </p>
(not needed for native link).</p>
<H3><a name="Ocaml_nn4"></a>31.1.2 Compiling the code</H3>
<p>
The OCaml SWIG module now requires you to compile a module (<tt>Swig</tt>)
The OCaml SWIG module now requires you to compile a module (<tt>Swig</tt>)
separately. In addition to aggregating common SWIG functionality, the Swig
module contains the data structure that represents C/C++ values. This allows
easier data sharing between modules if two or more are combined, because
@ -134,28 +136,29 @@ the type of each SWIG'ed module's c_obj is derived from Swig.c_obj_t. This
also allows SWIG to acquire new conversions painlessly, as well as giving
the user more freedom with respect to custom typing.
Use <tt>ocamlc</tt> or <tt>ocamlopt</tt> to compile your
SWIG interface like:
Use <tt>ocamlc</tt> or <tt>ocamlopt</tt> to compile your SWIG interface like:
</p>
<div class="code">
<pre>
<div class="code">
<pre>
% swig -ocaml -co swig.mli ; swig -ocaml co swig.ml
% ocamlc -c swig.mli ; ocamlc -c swig.ml
% ocamlc -c -ccopt "-I/usr/include/foo" example_wrap.c
% ocamlc -c example.mli
% ocamlc -c example.ml
</pre>
</pre>
</div>
<p> <tt>ocamlc</tt> is aware of .c files and knows how to handle them. Unfortunately,
it does not know about .cxx, .cc, or .cpp files, so when SWIG is invoked
in C++ mode, you must: </p>
<div class="code">
<pre>
% cp example_wrap.cxx example_wrap.cxx.c<br>% ocamlc -c ... -ccopt -xc++ example_wrap.cxx.c<br>% ...<br>
</pre>
<p><tt>ocamlc</tt> is aware of .c files and knows how to handle them. Unfortunately,
it does not know about .cxx, .cc, or .cpp files, so when SWIG is invoked
in C++ mode, you must:</p>
<div class="code">
<pre>
% cp example_wrap.cxx example_wrap.cxx.c
% ocamlc -c ... -ccopt -xc++ example_wrap.cxx.c
% ...
</pre>
</div>
<H3><a name="Ocaml_nn5"></a>31.1.3 The camlp4 module</H3>
@ -165,8 +168,8 @@ the user more freedom with respect to custom typing.
The camlp4 module (swigp4.ml -&gt; swigp4.cmo) contains a simple rewriter which
makes C++ code blend more seamlessly with objective caml code. Its use is
optional, but encouraged. The source file is included in the Lib/ocaml
directory of the SWIG source distribution. You can checkout this file with
<tt>"swig -ocaml -co swigp4.ml"</tt>. You should compile the file with
directory of the SWIG source distribution. You can checkout this file with
<tt>"swig -ocaml -co swigp4.ml"</tt>. You should compile the file with
<tt>"ocamlc -I `camlp4 -where` -pp 'camlp4o pa_extend.cmo q_MLast.cmo' -c swigp4.ml"</tt>
</p>
@ -192,7 +195,7 @@ a '+= b</td>
<td>
(invoke object) "+=" argument as in<br>
(invoke a) "+=" b<td></tr>
<tr><th colspan=2>Note that because camlp4 always recognizes &lt;&lt;
<tr><th colspan=2>Note that because camlp4 always recognizes &lt;&lt;
and &gt;&gt;, they are replaced by lsl and lsr in operator names.
<tr><td>
<i>'unop</i> object as in<br>
@ -241,11 +244,11 @@ let b = C_string (getenv "PATH")
You can test-drive your module by building a
toplevel ocaml interpreter. Consult the ocaml manual for details.
</p>
<p>
When linking any ocaml bytecode with your module, use the -custom
option to build your functions into the primitive list. This
option is not needed when you build native code.
option to build your functions into the primitive list. This
option is not needed when you build native code.
</p>
<H3><a name="Ocaml_nn7"></a>31.1.5 Compilation problems and compiling with C++</H3>
@ -273,9 +276,9 @@ In the code as seen by the typemap
writer, there is a value, swig_result, that always contains the
current return data. It is a list, and must be appended with the
caml_list_append function, or with functions and macros provided by
objective caml.<br>
objective caml.
</p>
<div class="code"><pre>
type c_obj =
C_void
@ -299,66 +302,65 @@ type c_obj =
</pre></div>
<p>
A few functions exist which generate and return these:
A few functions exist which generate and return these:
</p>
<ul>
<li>caml_ptr_val receives a c_obj and returns a void *. &nbsp;This
should be used for all pointer purposes.</li>
<li>caml_long_val receives a c_obj and returns a long. &nbsp;This
should be used for most integral purposes.<br>
</li>
<li>caml_val_ptr receives a void * and returns a c_obj.</li>
<li>caml_val_bool receives a C int and returns a c_obj representing
its bool value.</li>
<li>caml_val_(u)?(char|short|int|long|float|double) receives an
appropriate C value and returns a c_obj representing it.</li>
<li>caml_val_string receives a char * and returns a string value.</li>
<li>caml_val_string_len receives a char * and a length and returns
a string value.</li>
<li>caml_val_obj receives a void * and an object type and returns
a C_obj, which contains a closure giving method access.</li>
<li>caml_ptr_val receives a c_obj and returns a void *. This
should be used for all pointer purposes.</li>
<li>caml_long_val receives a c_obj and returns a long. This
should be used for most integral purposes.</li>
<li>caml_val_ptr receives a void * and returns a c_obj.</li>
<li>caml_val_bool receives a C int and returns a c_obj representing
its bool value.</li>
<li>caml_val_(u)?(char|short|int|long|float|double) receives an
appropriate C value and returns a c_obj representing it.</li>
<li>caml_val_string receives a char * and returns a string value.</li>
<li>caml_val_string_len receives a char * and a length and returns
a string value.</li>
<li>caml_val_obj receives a void * and an object type and returns
a C_obj, which contains a closure giving method access.</li>
</ul>
<p>
Because of this style, a typemap can return any kind of value it
wants from a function. &nbsp;This enables out typemaps and inout typemaps
to work well. &nbsp;The one thing to remember about outputting values
is that you must append them to the return list with swig_result = caml_list_append(swig_result,v).
wants from a function. This enables out typemaps and inout typemaps
to work well. The one thing to remember about outputting values
is that you must append them to the return list with swig_result = caml_list_append(swig_result,v).
</p>
<p>
&nbsp;This function will return a new list that has your element
appended. Upon return to caml space, the fnhelper function
beautifies the result. A list containing a single item degrades to
only that item (i.e. [ C_int 3 ] -&gt; C_int 3), and a list
containing more than one item is wrapped in C_list (i.e. [ C_char
'a' ; C_char 'b' -&gt; C_list [ C_char 'a' ; C_char b
]). &nbsp;This is in order to make return values easier to handle
when functions have only one return value, such as constructors,
and operators. &nbsp;In addition, string, pointer, and object
values are interchangeable with respect to caml_ptr_val, so you can
allocate memory as caml strings and still use the resulting
pointers for C purposes, even using them to construct simple objects
on. Note, though, that foreign C++ code does not respect the garbage
collector, although the SWIG interface does.</p>
This function will return a new list that has your element
appended. Upon return to caml space, the fnhelper function
beautifies the result. A list containing a single item degrades to
only that item (i.e. [ C_int 3 ] -&gt; C_int 3), and a list
containing more than one item is wrapped in C_list (i.e. [ C_char
'a' ; C_char 'b' -&gt; C_list [ C_char 'a' ; C_char b
]). This is in order to make return values easier to handle
when functions have only one return value, such as constructors,
and operators. In addition, string, pointer, and object
values are interchangeable with respect to caml_ptr_val, so you can
allocate memory as caml strings and still use the resulting
pointers for C purposes, even using them to construct simple objects
on. Note, though, that foreign C++ code does not respect the garbage
collector, although the SWIG interface does.</p>
<p>
The wild card type that you can use in lots of different ways is
C_obj. It allows you to wrap any type of thing you like as an
object using the same mechanism that the ocaml module
does. &nbsp;When evaluated in caml_ptr_val, the returned value is
the result of a call to the object's "&amp;" operator, taken as a pointer.
</p>
<p>
You should only construct values using objective caml, or using the
functions caml_val_* functions provided as static functions to a SWIG
ocaml module, as well as the caml_list_* functions. These functions
provide everything a typemap needs to produce values. In addition,
value items pass through directly, but you must make your own type
signature for a function that uses value in this way.
</p>
<p>
The wild card type that you can use in lots of different ways is
C_obj. It allows you to wrap any type of thing you like as an
object using the same mechanism that the ocaml module
does. When evaluated in caml_ptr_val, the returned value is
the result of a call to the object's "&amp;" operator, taken as a pointer.
</p>
<p>
You should only construct values using objective caml, or using the
functions caml_val_* functions provided as static functions to a SWIG
ocaml module, as well as the caml_list_* functions. These functions
provide everything a typemap needs to produce values. In addition,
value items pass through directly, but you must make your own type
signature for a function that uses value in this way.
</p>
<H3><a name="Ocaml_nn9"></a>31.2.1 The generated module</H3>
@ -376,7 +378,7 @@ that the keywords are not the same as the C++ ones.
You can introduce extra code into the output wherever you like with SWIG.
These are the places you can introduce code:
<table border="1" summary="Extra code sections">
<tr><td>"header"</td><td>This code is inserted near the beginning of the
<tr><td>"header"</td><td>This code is inserted near the beginning of the
C wrapper file, before any function definitions.</td></tr>
<tr><td>"wrapper"</td><td>This code is inserted in the function definition
section.</td></tr>
@ -385,25 +387,25 @@ file.</td></tr>
<tr><td>"mli"</td><td>This code is inserted into the caml interface file.
Special signatures should be inserted here.
</td></tr>
<tr><td>"ml"</td><td>This code is inserted in the caml code defining the
<tr><td>"ml"</td><td>This code is inserted in the caml code defining the
interface to your C code. Special caml code, as well as any initialization
which should run when the module is loaded may be inserted here.
</td></tr>
</td></tr>
<tr><td>"classtemplate"</td><td>The "classtemplate" place is special because
it describes the output SWIG will generate for class definitions.
</td></tr>
</table>
<H3><a name="Ocaml_nn10"></a>31.2.2 Enums</H3>
<p>
SWIG will wrap enumerations as polymorphic variants in the output
Ocaml code, as above in C_enum.&nbsp; In order to support all
Ocaml code, as above in C_enum. In order to support all
C++-style uses of enums, the function int_to_enum and enum_to_int are
provided for ocaml code to produce and consume these values as
integers. &nbsp;Other than that, correct uses of enums will not have
a problem. &nbsp;Since enum labels may overlap between enums, the
integers. Other than that, correct uses of enums will not have
a problem. Since enum labels may overlap between enums, the
enum_to_int and int_to_enum functions take an enum type label as an
argument. Example:
</p>
@ -416,9 +418,9 @@ enum c_enum_type { a = 1, b, c = 4, d = 8 };
enum c_enum_type { a = 1, b, c = 4, d = 8 };
</pre></div>
<p>
<p>
The output mli contains:
</p>
</p>
<div class="code"><pre>
type c_enum_type = [
@ -435,16 +437,16 @@ type c_enum_tag = [
val int_to_enum c_enum_type -&gt; int -&gt; c_obj
val enum_to_int c_enum_type -&gt; c_obj -&gt; c_obj
</pre>
</div>
</div>
<p>
So it's possible to do this:
So it's possible to do this:
</p>
<div class="code">
<pre>
<div class="code">
<pre>
bash-2.05a$ ocamlmktop -custom enum_test_wrap.o enum_test.cmo -o enum_test_top
bash-2.05a$ ./enum_test_top
bash-2.05a$ ./enum_test_top
Objective Caml version 3.04
# open Enum_test ;;
@ -455,7 +457,7 @@ val x : Enum_test.c_obj = C_enum `a
# int_to_enum `c_enum_type 4 ;;
- : Enum_test.c_obj = C_enum `c
</pre>
</div>
</div>
<H4><a name="Ocaml_nn11"></a>31.2.2.1 Enum typing in Ocaml</H4>
@ -485,7 +487,7 @@ distribution.
<p>
By including "carray.i", you will get access to some macros that help you
create typemaps for array types fairly easily.
create typemaps for array types fairly easily.
</p>
<p>
@ -547,7 +549,7 @@ void printfloats( float *tab, int len ) {
printf( "%f ", tab[i] );
}
printf( "\n" );
printf( "\n" );
}
%}
@ -577,25 +579,25 @@ void printfloats( float *tab, int len );
<p>
C++ classes, along with structs and unions are represented by C_obj
(string -&gt; c_obj -&gt; c_obj) wrapped closures. &nbsp;These objects
(string -&gt; c_obj -&gt; c_obj) wrapped closures. These objects
contain a method list, and a type, which allow them to be used like
C++ objects. When passed into typemaps that use pointers, they
degrade to pointers through their "&amp;" method. &nbsp;Every method
degrade to pointers through their "&amp;" method. Every method
an object has is represented as a string in the object's method table,
and each method table exists in memory only once. &nbsp;In addition
and each method table exists in memory only once. In addition
to any other operators an object might have, certain builtin ones are
provided by SWIG: (all of these take no arguments (C_void))
provided by SWIG: (all of these take no arguments (C_void))
</p>
<table summary="SWIG provided operators">
<tr><td>"~"</td><td>Delete this object</td></tr>
<tr><td>"&amp;"</td><td>Return an ordinary C_ptr value representing this
<tr><td>"&amp;"</td><td>Return an ordinary C_ptr value representing this
object's address</td></tr>
<tr><td>"sizeof"</td><td>If enabled with ("sizeof"="1") on the module node,
return the object's size in char.</td></tr>
<tr><td>":methods"</td><td>Returns a list of strings containing the names of
the methods this object contains</td></tr>
<tr><td>":classof"</td><td>Returns the name of the class this object belongs
<tr><td>":classof"</td><td>Returns the name of the class this object belongs
to.</td></tr>
<tr><td>":parents"</td><td>Returns a list of all direct parent classes which
have been wrapped by SWIG.</td></tr>
@ -603,8 +605,8 @@ have been wrapped by SWIG.</td></tr>
indicated parent class. This is mainly used internally by the SWIG module,
but may be useful to client programs.</td></tr>
<tr><td>"[member-variable]"</td><td>Each member variable is wrapped as a
method with an optional parameter.
Called with one argument, the member variable is set to the value of the
method with an optional parameter.
Called with one argument, the member variable is set to the value of the
argument. With zero arguments, the value is returned.
</td></tr>
</table>
@ -652,12 +654,12 @@ Since there's a makefile in that directory, the example is easy to build.
<p>
Here's a sample transcript of an interactive session using a string vector
after making a toplevel (make toplevel). This example uses the camlp4
after making a toplevel (make toplevel). This example uses the camlp4
module.
</p>
<div class="code"><pre>
bash-2.05a$ ./example_top
bash-2.05a$ ./example_top
Objective Caml version 3.06
Camlp4 Parsing version 3.06
@ -685,14 +687,14 @@ C_list
- : Example.c_obj = C_void
# x '[1] ;;
- : Example.c_obj = C_string "spam"
# for i = 0 to (x -&gt; size() as int) - 1 do
print_endline ((x '[i to int]) as string)
# for i = 0 to (x -&gt; size() as int) - 1 do
print_endline ((x '[i to int]) as string)
done ;;
foo
bar
baz
- : unit = ()
#
#
</pre></div>
<H4><a name="Ocaml_nn19"></a>31.2.4.2 C++ Class Example</H4>
@ -703,7 +705,7 @@ Here's a simple example using Trolltech's Qt Library:
</p>
<table border="1" bgcolor="#dddddd" summary="Qt Library example">
<tr><th><center>qt.i</center></th></tr>
<tr><th><center>qt.i</center></th></tr>
<tr><td><pre>
%module qt
%{
@ -733,9 +735,9 @@ bash-2.05a$ QTPATH=/your/qt/path
bash-2.05a$ for file in swig.mli swig.ml swigp4.ml ; do swig -ocaml -co $file ; done
bash-2.05a$ ocamlc -c swig.mli ; ocamlc -c swig.ml
bash-2.05a$ ocamlc -I `camlp4 -where` -pp "camlp4o pa_extend.cmo q_MLast.cmo" -c swigp4.ml
bash-2.05a$ swig -ocaml -c++ -I$QTPATH/include qt.i
bash-2.05a$ swig -ocaml -c++ -I$QTPATH/include qt.i
bash-2.05a$ mv qt_wrap.cxx qt_wrap.c
bash-2.05a$ ocamlc -c -ccopt -xc++ -ccopt -g -g -ccopt -I$QTPATH/include qt_wrap.c
bash-2.05a$ ocamlc -c -ccopt -xc++ -ccopt -g -g -ccopt -I$QTPATH/include qt_wrap.c
bash-2.05a$ ocamlc -c qt.mli
bash-2.05a$ ocamlc -c qt.ml
bash-2.05a$ ocamlmktop -custom swig.cmo -I `camlp4 -where` \
@ -747,7 +749,7 @@ bash-2.05a$ ocamlmktop -custom swig.cmo -I `camlp4 -where` \
<div class="code"><pre>
bash-2.05a$ ./qt_top
bash-2.05a$ ./qt_top
Objective Caml version 3.06
Camlp4 Parsing version 3.06
@ -767,7 +769,7 @@ val hello : Qt.c_obj = C_obj &lt;fun&gt;
<p>
Assuming you have a working installation of QT, you will see a window
containing the string "hi" in a button.
containing the string "hi" in a button.
</p>
<H3><a name="Ocaml_nn22"></a>31.2.5 Director Classes</H3>
@ -852,7 +854,7 @@ let triangle_class pts ob meth args =
| _ -&gt; (invoke ob) meth args ;;
let triangle =
new_derived_object
new_derived_object
new_shape
(triangle_class ((0.0,0.0),(0.5,1.0),(1.0,0.0)))
'() ;;
@ -896,7 +898,7 @@ The definition of the actual object triangle can be described this way:
<div class="code"><pre>
let triangle =
new_derived_object
new_derived_object
new_shape
(triangle_class ((0.0,0.0),(0.5,1.0),(1.0,0.0)))
'()
@ -904,13 +906,13 @@ let triangle =
<p>
The first argument to <tt>new_derived_object</tt>, new_shape is the method
which returns a shape instance. This function will be invoked with the
which returns a shape instance. This function will be invoked with the
third argument will be appended to the argument list [ C_void ]. In the
example, the actual argument list is sent as (C_list [ C_void ; C_void ]).
The augmented constructor for a director class needs the first argument
to determine whether it is being constructed as a derived object, or as
an object of the indicated type only (in this case <tt>shape</tt>). The
Second argument is a closure that will be added to the final C_obj.
Second argument is a closure that will be added to the final C_obj.
</p>
<p>