mirror of https://github.com/swig/swig
992 lines
34 KiB
HTML
992 lines
34 KiB
HTML
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
|
<html>
|
|
<head>
|
|
<title>SWIG and Ocaml</title>
|
|
<link rel="stylesheet" type="text/css" href="style.css">
|
|
</head>
|
|
<body bgcolor="#ffffff">
|
|
<a name="n1"></a>
|
|
<H1><a name="Ocaml"></a>25 SWIG and Ocaml</H1>
|
|
<!-- INDEX -->
|
|
<div class="sectiontoc">
|
|
<ul>
|
|
<li><a href="#Ocaml_nn2">Preliminaries</a>
|
|
<ul>
|
|
<li><a href="#Ocaml_nn3">Running SWIG</a>
|
|
<li><a href="#Ocaml_nn4">Compiling the code</a>
|
|
<li><a href="#Ocaml_nn5">The camlp4 module</a>
|
|
<li><a href="#Ocaml_nn6">Using your module</a>
|
|
<li><a href="#Ocaml_nn7">Compilation problems and compiling with C++</a>
|
|
</ul>
|
|
<li><a href="#Ocaml_nn8">The low-level Ocaml/C interface</a>
|
|
<ul>
|
|
<li><a href="#Ocaml_nn9">The generated module</a>
|
|
<li><a href="#Ocaml_nn10">Enums</a>
|
|
<ul>
|
|
<li><a href="#Ocaml_nn11">Enum typing in Ocaml</a>
|
|
</ul>
|
|
<li><a href="#Ocaml_nn12">Arrays</a>
|
|
<ul>
|
|
<li><a href="#Ocaml_nn13">Simple types of bounded arrays</a>
|
|
<li><a href="#Ocaml_nn14">Complex and unbounded arrays</a>
|
|
<li><a href="#Ocaml_nn15">Using an object</a>
|
|
<li><a href="#Ocaml_nn16">Example typemap for a function taking float * and int</a>
|
|
</ul>
|
|
<li><a href="#Ocaml_nn17">C++ Classes</a>
|
|
<ul>
|
|
<li><a href="#Ocaml_nn18">STL vector and string Example</a>
|
|
<li><a href="#Ocaml_nn19">C++ Class Example</a>
|
|
<li><a href="#Ocaml_nn20">Compiling the example</a>
|
|
<li><a href="#Ocaml_nn21">Sample Session</a>
|
|
</ul>
|
|
<li><a href="#Ocaml_nn22">Director Classes</a>
|
|
<ul>
|
|
<li><a href="#Ocaml_nn23">Director Introduction</a>
|
|
<li><a href="#Ocaml_nn24">Overriding Methods in Ocaml</a>
|
|
<li><a href="#Ocaml_nn25">Director Usage Example</a>
|
|
<li><a href="#Ocaml_nn26">Creating director objects</a>
|
|
<li><a href="#Ocaml_nn27">Typemaps for directors, <tt>directorin, directorout, directorargout</tt></a>
|
|
<li><a href="#Ocaml_nn28"><tt>directorin</tt> typemap</a>
|
|
<li><a href="#Ocaml_nn29"><tt>directorout</tt> typemap</a>
|
|
<li><a href="#Ocaml_nn30"><tt>directorargout</tt> typemap</a>
|
|
</ul>
|
|
<li><a href="#Ocaml_nn31">Exceptions</a>
|
|
</ul>
|
|
</ul>
|
|
</div>
|
|
<!-- INDEX -->
|
|
|
|
|
|
|
|
<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.
|
|
</p>
|
|
|
|
<p>
|
|
If you're not familiar with the Objective Caml language, you can visit
|
|
<a href="http://www.ocaml.org/">The Ocaml Website</a>.
|
|
</p>
|
|
|
|
<H2><a name="Ocaml_nn2"></a>25.1 Preliminaries</H2>
|
|
|
|
|
|
<p>
|
|
SWIG 1.3 works with Ocaml 3.04 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://www.ocaml-programming.de/packages/documentation/dl/">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>
|
|
|
|
<H3><a name="Ocaml_nn3"></a>25.1.1 Running SWIG</H3>
|
|
|
|
|
|
<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.
|
|
</p>
|
|
|
|
<div class="code">
|
|
<pre>
|
|
%swig -ocaml example.i
|
|
</pre>
|
|
</div>
|
|
|
|
<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
|
|
<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>
|
|
|
|
<H3><a name="Ocaml_nn4"></a>25.1.2 Compiling the code</H3>
|
|
|
|
|
|
<p>
|
|
The O'Caml 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
|
|
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:
|
|
</p>
|
|
|
|
<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>
|
|
</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>
|
|
</div>
|
|
|
|
<H3><a name="Ocaml_nn5"></a>25.1.3 The camlp4 module</H3>
|
|
|
|
|
|
<p>
|
|
The camlp4 module (swigp4.ml -> swigp4.cmo) contains a simple rewriter which
|
|
makes C++ code blend more seamlessly with objective caml code. It's 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
|
|
<tt>"ocamlc -I `camlp4 -where` -pp 'camlp4o pa_extend.cmo q_MLast.cmo' -c swigp4.ml"</tt>
|
|
</p>
|
|
|
|
<p>
|
|
The basic principle of the module is to recognize certain non-caml expressions
|
|
and convert them for use with C++ code as interfaced by SWIG. The camlp4
|
|
module is written to work with generated SWIG interfaces, and probably isn't
|
|
great to use with anything else.
|
|
</p>
|
|
|
|
<p>
|
|
Here are the main rewriting rules:
|
|
</p>
|
|
|
|
<table border="1" summary="Rewriting rules">
|
|
<tr><th>Input</th><th>Rewritten to</th></tr>
|
|
<tr><td>f'( ... ) as in<br> atoi'("0") or<br> _exit'(0)</td>
|
|
<td>f(C_list [ ... ]) as in<br> atoi (C_list [ C_string "0" ]) or<br> _exit (C_list [ C_int 0 ])</td></tr>
|
|
<tr><td>object -> method ( ... )</td><td>(invoke object) "method" (C_list [ ... ])</td></tr>
|
|
<tr><td>
|
|
object <i>'binop</i> argument as in<br>
|
|
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 <<
|
|
and >>, they are replaced by lsl and lsr in operator names.
|
|
<tr><td>
|
|
<i>'unop</i> object as in<br>
|
|
'! a
|
|
</td><td>
|
|
(invoke a) "!" C_void</td></tr>
|
|
<tr><td>
|
|
<b>Smart pointer access like this</b><br>
|
|
object '-> method ( args )<br>
|
|
</td><td>
|
|
(invoke (invoke object "->" C_void))
|
|
</td></tr>
|
|
<tr><td>
|
|
<b>Invoke syntax</b><br>
|
|
object . '( ... )
|
|
</td><td>
|
|
(invoke object) "()" (C_list [ ... ])
|
|
</td></tr>
|
|
<tr><td>
|
|
<b>Array syntax</b><br>
|
|
object '[ 10 ]
|
|
</td><td>
|
|
(invoke object) "[]" (C_int 10)
|
|
</td></tr>
|
|
<tr><td>
|
|
<b>Assignment syntax</b><br>
|
|
let a = '10 and b = '"foo" and c = '1.0 and d = 'true
|
|
</td><td>
|
|
let a = C_int 10 and b = C_string "foo" and c = C_double 1.0 and d = C_bool true
|
|
</td></tr>
|
|
<tr><td>
|
|
<b>Cast syntax</b><br>
|
|
let a = _atoi '("2") as int<br>
|
|
let b = (getenv "PATH") to string<br>
|
|
This works for int, string, float, bool
|
|
</td><td>
|
|
let a = get_int (_atoi (C_string "2"))<br>
|
|
let b = C_string (getenv "PATH")
|
|
</td></tr>
|
|
</table>
|
|
|
|
<H3><a name="Ocaml_nn6"></a>25.1.4 Using your module</H3>
|
|
|
|
|
|
<p>
|
|
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.
|
|
</p>
|
|
|
|
<H3><a name="Ocaml_nn7"></a>25.1.5 Compilation problems and compiling with C++</H3>
|
|
|
|
|
|
<p>
|
|
As mentioned above, .cxx files need special
|
|
handling to be compiled with <tt>ocamlc</tt>. Other than that, C code
|
|
that uses <tt>class</tt> as a non-keyword, and C code that is too
|
|
liberal with pointer types may not compile under the C++ compiler.
|
|
Most code meant to be compiled as C++ will not have problems.
|
|
</p>
|
|
|
|
<H2><a name="Ocaml_nn8"></a>25.2 The low-level Ocaml/C interface</H2>
|
|
|
|
|
|
<p>
|
|
In order to provide access to overloaded functions, and
|
|
provide sensible outputs from them, all C entities are represented as
|
|
members of the c_obj type:
|
|
</p>
|
|
|
|
<p>
|
|
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>
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
type c_obj =
|
|
C_void
|
|
| C_bool of bool
|
|
| C_char of char
|
|
| C_uchar of char
|
|
| C_short of int
|
|
| C_ushort of int
|
|
| C_int of int
|
|
| C_uint of int32
|
|
| C_int32 of int32
|
|
| C_int64 of int64
|
|
| C_float of float
|
|
| C_double of float
|
|
| C_ptr of int64 * int64
|
|
| C_array of c_obj array
|
|
| C_list of c_obj list
|
|
| C_obj of (string -> c_obj -> c_obj)
|
|
| C_string of string
|
|
| C_enum of c_enum_t
|
|
</pre></div>
|
|
|
|
<p>
|
|
A few functions exist which generate and return these:
|
|
</p>
|
|
|
|
<ul>
|
|
<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.<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
|
|
it's 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. 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>
|
|
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 ] -> C_int 3), and a list
|
|
containing more than one item is wrapped in C_list (i.e. [ C_char
|
|
'a' ; C_char 'b' -> 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. When evaluated in caml_ptr_val, the returned value is
|
|
the result of a call to the object's "&" 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>25.2.1 The generated module</H3>
|
|
|
|
|
|
<p>
|
|
The SWIG <tt>%module</tt> directive specifies the name of the Ocaml
|
|
module to be generated. If you specified `<tt>%module example</tt>',
|
|
then your Ocaml code will be accessible in the module Example. The
|
|
module name is always capitalized as is the ocaml convention. Note
|
|
that you must not use any Ocaml keyword to name your module. Remember
|
|
that the keywords are not the same as the C++ ones.
|
|
</p>
|
|
|
|
<p>
|
|
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
|
|
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>
|
|
<tr><td>"runtime"</td><td>This code is inserted near the end of the C wrapper
|
|
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
|
|
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>
|
|
<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>25.2.2 Enums</H3>
|
|
|
|
|
|
<p>
|
|
SWIG will wrap enumerations as polymorphic variants in the output
|
|
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. 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>
|
|
|
|
<div class="code"><pre>
|
|
%module enum_test
|
|
%{
|
|
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>
|
|
The output mli contains:
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
type c_enum_type = [
|
|
`unknown
|
|
| `c_enum_type
|
|
]
|
|
type c_enum_tag = [
|
|
`int of int
|
|
| `a
|
|
| `b
|
|
| `c
|
|
| `d
|
|
]
|
|
val int_to_enum c_enum_type -> int -> c_obj
|
|
val enum_to_int c_enum_type -> c_obj -> c_obj
|
|
</pre>
|
|
</div>
|
|
|
|
<p>
|
|
So it's possible to do this:
|
|
</p>
|
|
|
|
<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
|
|
Objective Caml version 3.04
|
|
|
|
# open Enum_test ;;
|
|
# let x = C_enum `a ;;
|
|
val x : Enum_test.c_obj = C_enum `a
|
|
# enum_to_int `c_enum_type x ;;
|
|
- : Enum_test.c_obj = C_int 1
|
|
# int_to_enum `c_enum_type 4 ;;
|
|
- : Enum_test.c_obj = C_enum `c
|
|
</pre>
|
|
</div>
|
|
|
|
<H4><a name="Ocaml_nn11"></a>25.2.2.1 Enum typing in Ocaml</H4>
|
|
|
|
|
|
<p>
|
|
The ocaml SWIG module now has support for loading and using multiple SWIG
|
|
modules at the same time. This enhances modularity, but presents problems
|
|
when used with a language which assumes that each module's types are complete
|
|
at compile time. In order to achieve total soundness enum types are now
|
|
isolated per-module. The type issue matters when values are shared between
|
|
functions imported from different modules. You must convert values to master
|
|
values using the swig_val function before sharing them with another module.
|
|
</p>
|
|
|
|
<H3><a name="Ocaml_nn12"></a>25.2.3 Arrays</H3>
|
|
|
|
|
|
<H4><a name="Ocaml_nn13"></a>25.2.3.1 Simple types of bounded arrays</H4>
|
|
|
|
|
|
<p>
|
|
SWIG has support for array types, but you generally will need to provide
|
|
a typemap to handle them. You can currently roll your own, or expand
|
|
some of the macros provided (but not included by default) with the SWIG
|
|
distribution.
|
|
</p>
|
|
|
|
<p>
|
|
By including "carray.i", you will get access to some macros that help you
|
|
create typemaps for array types fairly easily.
|
|
</p>
|
|
|
|
<p>
|
|
<tt>%make_simple_array_typemap</tt> is the easiest way to get access to
|
|
arrays of simple types with known bounds in your code, but this only works
|
|
for arrays whose bounds are completely specified.
|
|
</p>
|
|
|
|
<H4><a name="Ocaml_nn14"></a>25.2.3.2 Complex and unbounded arrays</H4>
|
|
|
|
|
|
<p>
|
|
Unfortunately, unbounded arrays and pointers can't be handled in a
|
|
completely general way by SWIG, because the end-condition of such an
|
|
array can't be predicted. In some cases, it will be by consent
|
|
(e.g. an array of four or more chars), sometimes by explicit length
|
|
(char *buffer, int len), and sometimes by sentinel value (0,-1,etc.).
|
|
SWIG can't predict which of these methods will be used in the array,
|
|
so you have to specify it for yourself in the form of a typemap.
|
|
</p>
|
|
|
|
<H4><a name="Ocaml_nn15"></a>25.2.3.3 Using an object</H4>
|
|
|
|
|
|
<p>
|
|
It's possible to use C++ to your advantage by creating a simple object that
|
|
provides access to your array. This may be more desirable in some cases,
|
|
since the object can provide bounds checking, etc., that prevents crashes.
|
|
</p>
|
|
|
|
<p>
|
|
Consider writing an object when the ending condition of your array is complex,
|
|
such as using a required sentinel, etc.
|
|
</p>
|
|
|
|
<H4><a name="Ocaml_nn16"></a>25.2.3.4 Example typemap for a function taking float * and int</H4>
|
|
|
|
|
|
<p>
|
|
This is a simple example <tt>in</tt> typemap for an array of float, where the
|
|
length of the array is specified as an extra parameter. Other such typemaps
|
|
will work similarly. In the example, the function printfloats is called with
|
|
a float array, and specified length. The actual length reported in the len
|
|
argument is the length of the array passed from ocaml, making passing an array
|
|
into this type of function convenient.
|
|
</p>
|
|
|
|
<table border="1" bgcolor="#dddddd" summary="float * and int typemap example">
|
|
<tr><th><center>tarray.i</center></th></tr>
|
|
<tr><td><pre>
|
|
%module tarray
|
|
%{
|
|
#include <stdio.h>
|
|
|
|
void printfloats( float *tab, int len ) {
|
|
int i;
|
|
|
|
for( i = 0; i < len; i++ ) {
|
|
printf( "%f ", tab[i] );
|
|
}
|
|
|
|
printf( "\n" );
|
|
}
|
|
%}
|
|
|
|
%typemap(in) (float *tab, int len) {
|
|
int i;
|
|
/* $*1_type */
|
|
$2 = caml_array_len($input);
|
|
$1 = ($*1_type *)malloc( $2 * sizeof( float ) );
|
|
for( i = 0; i < $2; i++ ) {
|
|
$1[i] = caml_double_val(caml_array_nth($input,i));
|
|
}
|
|
}
|
|
|
|
void printfloats( float *tab, int len );
|
|
</pre></td></tr>
|
|
<tr><th>Sample Run</th></tr>
|
|
<tr><td><pre>
|
|
# open Tarray ;;
|
|
# _printfloats (C_array [| C_double 1.0 ; C_double 3.0 ; C_double 5.6666 |]) ;;
|
|
1.000000 3.000000 5.666600
|
|
- : Tarray.c_obj = C_void
|
|
</pre></td></tr></table>
|
|
|
|
|
|
<H3><a name="Ocaml_nn17"></a>25.2.4 C++ Classes</H3>
|
|
|
|
|
|
<p>
|
|
C++ classes, along with structs and unions are represented by C_obj
|
|
(string -> c_obj -> 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 "&" 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. 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))
|
|
</p>
|
|
|
|
<table summary="SWIG provided operators">
|
|
<tr><td>"~"</td><td>Delete this object</td></tr>
|
|
<tr><td>"&"</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
|
|
to.</td></tr>
|
|
<tr><td>":parents"</td><td>Returns a list of all direct parent classes which
|
|
have been wrapped by SWIG.</td></tr>
|
|
<tr><td>"::[parent-class]"</td><td>Returns a view of the object as the
|
|
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
|
|
argument. With zero arguments, the value is returned.
|
|
</td></tr>
|
|
</table>
|
|
|
|
<p>
|
|
Note that this string belongs to the wrapper object, and not
|
|
the underlying pointer, so using create_[x]_from_ptr alters the
|
|
returned value for the same object.
|
|
</p>
|
|
|
|
<H4><a name="Ocaml_nn18"></a>25.2.4.1 STL vector and string Example</H4>
|
|
|
|
|
|
<p>
|
|
Standard typemaps are now provided for STL vector and string. More are in
|
|
the works. STL strings are passed just like normal strings, and returned
|
|
as strings. STL string references don't mutate the original string, (which
|
|
might be surprising), because Ocaml strings are mutable but have fixed
|
|
length. Instead, use multiple returns, as in the argout_ref example.
|
|
</p>
|
|
|
|
<table border="1" bgcolor="#dddddd" summary="STL vector and string example">
|
|
<tr><th><center>example.i</center></th></tr>
|
|
<tr><td><pre>
|
|
%module example
|
|
%{
|
|
#include "example.h"
|
|
%}
|
|
|
|
%include stl.i
|
|
|
|
namespace std {
|
|
%template(StringVector) std::vector < string >;
|
|
};
|
|
|
|
%include example.h
|
|
</pre></td></tr>
|
|
<tr><td><font size="-1"><i>This example is in Examples/ocaml/stl
|
|
</i></font></td></tr>
|
|
</table>
|
|
|
|
<p>
|
|
Since there's a makefile in that directory, the example is easy to build.
|
|
</p>
|
|
|
|
<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
|
|
module.
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
bash-2.05a$ ./example_top
|
|
Objective Caml version 3.06
|
|
|
|
Camlp4 Parsing version 3.06
|
|
|
|
# open Swig ;;
|
|
# open Example ;;
|
|
# let x = new_StringVector '() ;;
|
|
val x : Example.c_obj = C_obj <fun>
|
|
# x -> ":methods" () ;;
|
|
- : Example.c_obj =
|
|
C_list
|
|
[C_string "nop"; C_string "size"; C_string "empty"; C_string "clear";
|
|
C_string "push_back"; C_string "[]"; C_string "="; C_string "set";
|
|
C_string "~"; C_string "&"; C_string ":parents"; C_string ":classof";
|
|
C_string ":methods"]
|
|
# x -> push_back ("foo") ;;
|
|
- : Example.c_obj = C_void
|
|
# x -> push_back ("bar") ;;
|
|
- : Example.c_obj = C_void
|
|
# x -> push_back ("baz") ;;
|
|
- : Example.c_obj = C_void
|
|
# x '[1] ;;
|
|
- : Example.c_obj = C_string "bar"
|
|
# x -> set (1,"spam") ;;
|
|
- : Example.c_obj = C_void
|
|
# x '[1] ;;
|
|
- : Example.c_obj = C_string "spam"
|
|
# for i = 0 to (x -> 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>25.2.4.2 C++ Class Example</H4>
|
|
|
|
|
|
<p>
|
|
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><td><pre>
|
|
%module qt
|
|
%{
|
|
#include <qapplication.h>
|
|
#include <qpushbutton.h>
|
|
%}
|
|
class QApplication {
|
|
public:
|
|
QApplication( int argc, char **argv );
|
|
void setMainWidget( QWidget *widget );
|
|
void exec();
|
|
};
|
|
|
|
class QPushButton {
|
|
public:
|
|
QPushButton( char *str, QWidget *w );
|
|
void resize( int x, int y );
|
|
void show();
|
|
};
|
|
</pre></td></tr></table>
|
|
|
|
<H4><a name="Ocaml_nn20"></a>25.2.4.3 Compiling the example</H4>
|
|
|
|
|
|
<div class="code"><pre>
|
|
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$ 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 qt.mli
|
|
bash-2.05a$ ocamlc -c qt.ml
|
|
bash-2.05a$ ocamlmktop -custom swig.cmo -I `camlp4 -where` \
|
|
camlp4o.cma swigp4.cmo qt_wrap.o qt.cmo -o qt_top -cclib \
|
|
-L$QTPATH/lib -cclib -lqt
|
|
</pre></div>
|
|
|
|
<H4><a name="Ocaml_nn21"></a>25.2.4.4 Sample Session</H4>
|
|
|
|
|
|
<div class="code"><pre>
|
|
bash-2.05a$ ./qt_top
|
|
Objective Caml version 3.06
|
|
|
|
Camlp4 Parsing version 3.06
|
|
|
|
# open Swig ;;
|
|
# open Qt ;;
|
|
# let a = new_QApplication '(0,0) ;;
|
|
val a : Qt.c_obj = C_obj <fun>
|
|
# let hello = new_QPushButton '("hi",0) ;;
|
|
val hello : Qt.c_obj = C_obj <fun>
|
|
# hello -> resize (100,30) ;;
|
|
- : Qt.c_obj = C_void
|
|
# hello -> show () ;;
|
|
- : Qt.c_obj = C_void
|
|
# a -> exec () ;;
|
|
</pre></div>
|
|
|
|
<p>
|
|
Assuming you have a working installation of QT, you will see a window
|
|
containing the string "hi" in a button.
|
|
</p>
|
|
|
|
<H3><a name="Ocaml_nn22"></a>25.2.5 Director Classes</H3>
|
|
|
|
|
|
<H4><a name="Ocaml_nn23"></a>25.2.5.1 Director Introduction</H4>
|
|
|
|
|
|
<p>
|
|
Director classes are classes which allow Ocaml code to override the public
|
|
methods of a C++ object. This facility allows the user to use C++ libraries
|
|
that require a derived class to provide application specific functionality in
|
|
the context of an application or utility framework.
|
|
</p>
|
|
|
|
<p>
|
|
You can turn on director classes by using an optional module argument like
|
|
this:
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
%module(directors="1")
|
|
|
|
...
|
|
|
|
// Turn on the director class for a specific class like this:
|
|
%feature("director")
|
|
class foo {
|
|
...
|
|
};
|
|
</pre></div>
|
|
|
|
<H4><a name="Ocaml_nn24"></a>25.2.5.2 Overriding Methods in Ocaml</H4>
|
|
|
|
|
|
<p>
|
|
Because the Ocaml language module treats C++ method calls as calls to a
|
|
certain function, all you need to do is to define the function that will
|
|
handle the method calls in terms of the public methods of the object, and
|
|
any other relevant information. The function <tt>new_derived_object</tt>
|
|
uses a stub class to call your methods in place of the ones provided by the
|
|
underlying implementation. The object you receive is the underlying object,
|
|
so you are free to call any methods you want from within your derived method.
|
|
Note that calls to the underlying object do not invoke Ocaml code. You need
|
|
to handle that yourself.
|
|
</p>
|
|
|
|
<p>
|
|
<tt>new_derived_object</tt> receives your function, the function that creates
|
|
the underlying object, and any constructor arguments, and provides an
|
|
object that you can use in any usual way. When C++ code calls one of the
|
|
object's methods, the object invokes the Ocaml function as if it had been
|
|
invoked from Ocaml, allowing any method definitions to override the C++ ones.
|
|
</p>
|
|
|
|
<p>
|
|
In this example, I'll examine the objective caml code involved in providing
|
|
an overloaded class. This example is contained in Examples/ocaml/shapes.
|
|
</p>
|
|
|
|
<H4><a name="Ocaml_nn25"></a>25.2.5.3 Director Usage Example</H4>
|
|
|
|
|
|
<table border="1" bgcolor="#dddddd" summary="Director usage example">
|
|
<tr><th><center>example_prog.ml</center>
|
|
</th></tr>
|
|
<tr><td><pre>
|
|
open Swig
|
|
open Example
|
|
|
|
...
|
|
|
|
let triangle_class pts ob meth args =
|
|
match meth with
|
|
"cover" ->
|
|
(match args with
|
|
C_list [ x_arg ; y_arg ] ->
|
|
let xa = x_arg as float
|
|
and ya = y_arg as float in
|
|
(point_in_triangle pts xa ya) to bool
|
|
| _ -> raise (Failure "cover needs two double arguments."))
|
|
| _ -> (invoke ob) meth args ;;
|
|
|
|
let triangle =
|
|
new_derived_object
|
|
new_shape
|
|
(triangle_class ((0.0,0.0),(0.5,1.0),(1.0,0.0)))
|
|
'() ;;
|
|
|
|
let _ = _draw_shape_coverage '(triangle, C_int 60, C_int 20) ;;
|
|
</pre></td></tr>
|
|
</table>
|
|
|
|
<p>
|
|
This is the meat of what you need to do. The actual "class" definition
|
|
containing the overloaded method is defined in the function triangle_class.
|
|
This is a lot like the class definitions emitted by SWIG, if you look at
|
|
example.ml, which is generated when SWIG consumes example.i. Basically,
|
|
you are given the arguments as a c_obj and the method name as a string, and
|
|
you must intercept the method you are interested in and provide whatever
|
|
return value you need. Bear in mind that the underlying C++ code needs the
|
|
right return type, or an exception will be thrown. This exception will
|
|
generally be Failure, or NotObject. You must call other ocaml methods that
|
|
you rely on yourself. Due to the way directors are implemented, method
|
|
calls on your object from with ocaml code will always invoke C++ methods
|
|
even if they are overridden in ocaml.
|
|
</p>
|
|
|
|
<p>
|
|
In the example, the draw_shape_coverage function plots the indicated number
|
|
of points as either covered (<tt>x</tt>) or uncovered ( ) between
|
|
0 and 1 on the X and Y axes. Your shape implementation can provide any
|
|
coverage map it likes, as long as it responds to the "cover" method call
|
|
with a boolean return (the underlying method returns bool). This might allow
|
|
a tricky shape implementation, such as a boolean combination, to be expressed
|
|
in a more effortless style in ocaml, while leaving the "engine" part of the
|
|
program in C++.
|
|
</p>
|
|
|
|
<H4><a name="Ocaml_nn26"></a>25.2.5.4 Creating director objects</H4>
|
|
|
|
|
|
<p>
|
|
The definition of the actual object triangle can be described this way:
|
|
</p>
|
|
|
|
<div class="code"><pre>
|
|
let triangle =
|
|
new_derived_object
|
|
new_shape
|
|
(triangle_class ((0.0,0.0),(0.5,1.0),(1.0,0.0)))
|
|
'()
|
|
</pre></div>
|
|
|
|
<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
|
|
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.
|
|
</p>
|
|
|
|
<p>
|
|
The actual object passed to the self parameter of the director object will
|
|
be a C_director_core, containing a c_obj option ref and a c_obj. The
|
|
c_obj provided is the same object that will be returned from new_derived
|
|
object, that is, the object exposing the overridden methods. The other part
|
|
is an option ref that will have its value extracted before becoming the
|
|
<tt>ob</tt> parameter of your class closure. This ref will contain
|
|
<tt>None</tt> if the C++ object underlying is ever destroyed, and will
|
|
consequently trigger an exception when any method is called on the object
|
|
after that point (the actual raise is from an inner function used by
|
|
new_derived_object, and throws NotObject). This prevents a deleted C++
|
|
object from causing a core dump, as long as the object is destroyed
|
|
properly.
|
|
</p>
|
|
|
|
<H4><a name="Ocaml_nn27"></a>25.2.5.5 Typemaps for directors, <tt>directorin, directorout, directorargout</tt></H4>
|
|
|
|
|
|
<p>
|
|
Special typemaps exist for use with directors, the <tt>directorin, directorout, directorargout</tt>
|
|
are used in place of <tt>in, out, argout</tt> typemaps, except that their
|
|
direction is reversed. They provide for you to provide argout values, as
|
|
well as a function return value in the same way you provide function arguments,
|
|
and to receive arguments the same way you normally receive function returns.
|
|
</p>
|
|
|
|
<H4><a name="Ocaml_nn28"></a>25.2.5.6 <tt>directorin</tt> typemap</H4>
|
|
|
|
|
|
<p>
|
|
The <tt>directorin</tt> typemap is used when you will receive arguments from a call
|
|
made by C++ code to you, therefore, values will be translated from C++ to
|
|
ocaml. You must provide some valid C_obj value. This is the value your ocaml
|
|
code receives when you are called. In general, a simple <tt>directorin</tt> typemap
|
|
can use the same body as a simple <tt>out</tt> typemap.
|
|
</p>
|
|
|
|
<H4><a name="Ocaml_nn29"></a>25.2.5.7 <tt>directorout</tt> typemap</H4>
|
|
|
|
|
|
<p>
|
|
The <tt>directorout</tt> typemap is used when you will send an argument from your
|
|
code back to the C++ caller. That is; directorout specifies a function return
|
|
conversion. You can usually use the same body as an <tt>in</tt> typemap
|
|
for the same type, except when there are special requirements for object
|
|
ownership, etc.
|
|
</p>
|
|
|
|
<H4><a name="Ocaml_nn30"></a>25.2.5.8 <tt>directorargout</tt> typemap</H4>
|
|
|
|
|
|
<p>
|
|
C++ allows function arguments which are by pointer (*) and by reference (&)
|
|
to receive a value from the called function, as well as sending one there.
|
|
Sometimes, this is the main purpose of the argument given. <tt>directorargout</tt>
|
|
typemaps allow your caml code to emulate this by specifying additional return
|
|
values to be put into the output parameters. The SWIG ocaml module is a bit
|
|
loose in order to make code easier to write. In this case, your return to
|
|
the caller must be a list containing the normal function return first, followed
|
|
by any argout values in order. These argout values will be taken from the
|
|
list and assigned to the values to be returned to C++ through directorargout typemaps.
|
|
In the event that you don't specify all of the necessary values, integral
|
|
values will read zero, and struct or object returns have undefined results.
|
|
</p>
|
|
|
|
<H3><a name="Ocaml_nn31"></a>25.2.6 Exceptions</H3>
|
|
|
|
|
|
<p>
|
|
Catching exceptions is now supported using SWIG's %exception feature. A simple
|
|
but not too useful example is provided by the throw_exception testcase in
|
|
Examples/test-suite. You can provide your own exceptions, too.
|
|
</p>
|
|
|
|
</body>
|
|
</html>
|