Thousands of changes to correct incorrect HTML. HTML is now valid (transitional 4.01).
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@6074 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
parent
7cb896a5f4
commit
aa4d1d907d
31 changed files with 6754 additions and 4801 deletions
|
|
@ -6,47 +6,47 @@
|
|||
</head>
|
||||
<body bgcolor="#ffffff">
|
||||
<a name="n1"></a>
|
||||
<a name="n1"></a><H1>19 SWIG and Ocaml</H1>
|
||||
<H1><a name="Ocaml"></a>21 SWIG and Ocaml</H1>
|
||||
<!-- INDEX -->
|
||||
<ul>
|
||||
<li><a href="#n2">Preliminaries</a>
|
||||
<li><a href="#Ocaml_nn2">Preliminaries</a>
|
||||
<ul>
|
||||
<li><a href="#n3">Running SWIG</a>
|
||||
<li><a href="#n4">Compiling the code</a>
|
||||
<li><a href="#n5">The camlp4 module</a>
|
||||
<li><a href="#n6">Using your module</a>
|
||||
<li><a href="#n7">Compilation problems and compiling with C++</a>
|
||||
<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="#n8">The low-level Ocaml/C interface</a>
|
||||
<li><a href="#Ocaml_nn8">The low-level Ocaml/C interface</a>
|
||||
<ul>
|
||||
<li><a href="#n9">The generated module</a>
|
||||
<li><a href="#n10">Enums</a>
|
||||
<li><a href="#n11">Arrays</a>
|
||||
<li><a href="#Ocaml_nn9">The generated module</a>
|
||||
<li><a href="#Ocaml_nn10">Enums</a>
|
||||
<li><a href="#Ocaml_nn11">Arrays</a>
|
||||
<ul>
|
||||
<li><a href="#n12">Simple types of bounded arrays</a>
|
||||
<li><a href="#n13">Complex and unbounded arrays</a>
|
||||
<li><a href="#n14">Using an object</a>
|
||||
<li><a href="#n15">Example typemap for a function taking float * and int</a>
|
||||
<li><a href="#Ocaml_nn12">Simple types of bounded arrays</a>
|
||||
<li><a href="#Ocaml_nn13">Complex and unbounded arrays</a>
|
||||
<li><a href="#Ocaml_nn14">Using an object</a>
|
||||
<li><a href="#Ocaml_nn15">Example typemap for a function taking float * and int</a>
|
||||
</ul>
|
||||
<li><a href="#n16">C++ Classes</a>
|
||||
<li><a href="#Ocaml_nn16">C++ Classes</a>
|
||||
<ul>
|
||||
<li><a href="#n17">STL vector and string Example</a>
|
||||
<li><a href="#n18">C++ Class Example</a>
|
||||
<li><a href="#n19">Compiling the example</a>
|
||||
<li><a href="#n20">Sample Session</a>
|
||||
<li><a href="#Ocaml_nn17">STL vector and string Example</a>
|
||||
<li><a href="#Ocaml_nn18">C++ Class Example</a>
|
||||
<li><a href="#Ocaml_nn19">Compiling the example</a>
|
||||
<li><a href="#Ocaml_nn20">Sample Session</a>
|
||||
</ul>
|
||||
<li><a href="#n21">Director Classes</a>
|
||||
<li><a href="#Ocaml_nn21">Director Classes</a>
|
||||
<ul>
|
||||
<li><a href="#n22">Director Introduction</a>
|
||||
<li><a href="#n23">Overriding Methods in Ocaml</a>
|
||||
<li><a href="#n24">Director Usage Example</a>
|
||||
<li><a href="#n25">Creating director objects</a>
|
||||
<li><a href="#n26">Typemaps for directors, <tt>directorin, directorout, directorargout</tt></a>
|
||||
<li><a href="#n27"><tt>directorin</tt> typemap</a>
|
||||
<li><a href="#n28"><tt>directorout</tt> typemap</a>
|
||||
<li><a href="#n29"><tt>directorargout</tt> typemap</a>
|
||||
<li><a href="#Ocaml_nn22">Director Introduction</a>
|
||||
<li><a href="#Ocaml_nn23">Overriding Methods in Ocaml</a>
|
||||
<li><a href="#Ocaml_nn24">Director Usage Example</a>
|
||||
<li><a href="#Ocaml_nn25">Creating director objects</a>
|
||||
<li><a href="#Ocaml_nn26">Typemaps for directors, <tt>directorin, directorout, directorargout</tt></a>
|
||||
<li><a href="#Ocaml_nn27"><tt>directorin</tt> typemap</a>
|
||||
<li><a href="#Ocaml_nn28"><tt>directorout</tt> typemap</a>
|
||||
<li><a href="#Ocaml_nn29"><tt>directorargout</tt> typemap</a>
|
||||
</ul>
|
||||
<li><a href="#n30">Exceptions</a>
|
||||
<li><a href="#Ocaml_nn30">Exceptions</a>
|
||||
</ul>
|
||||
</ul>
|
||||
<!-- INDEX -->
|
||||
|
|
@ -73,7 +73,7 @@ If you're not familiar with the Objective Caml language, you can visit
|
|||
<a href="http://www.ocaml.org/">The Ocaml Website</a>.
|
||||
</p>
|
||||
|
||||
<a name="n2"></a><H2>19.1 Preliminaries</H2>
|
||||
<H2><a name="Ocaml_nn2"></a>21.1 Preliminaries</H2>
|
||||
|
||||
|
||||
SWIG 1.3 works with Ocaml 3.04 and above. Given the choice,
|
||||
|
|
@ -90,7 +90,7 @@ usual -lxxx against libxxx.so, as well as with Gerd Stolpmann's
|
|||
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.
|
||||
|
||||
<a name="n3"></a><H3>19.1.1 Running SWIG</H3>
|
||||
<H3><a name="Ocaml_nn3"></a>21.1.1 Running SWIG</H3>
|
||||
|
||||
|
||||
The basics of getting a SWIG Ocaml module up and running
|
||||
|
|
@ -99,7 +99,9 @@ will be loaded dynamically. This has only been tested on Linux so far.
|
|||
option.
|
||||
|
||||
<blockquote>
|
||||
<pre>%swig -ocaml example.i</pre>
|
||||
<pre>
|
||||
%swig -ocaml example.i
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<p> This will produce 3 files. The file <tt>example_wrap.c</tt> contains
|
||||
|
|
@ -109,9 +111,10 @@ you will compile the file <tt>example_wrap.c</tt> with <tt>ocamlc</tt> or
|
|||
the resulting .ml and .mli files as well, and do the final link with -custom
|
||||
(not needed for native link). </p>
|
||||
|
||||
<a name="n4"></a><H3>19.1.2 Compiling the code</H3>
|
||||
<H3><a name="Ocaml_nn4"></a>21.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
|
||||
|
|
@ -122,7 +125,7 @@ the user more freedom with respect to custom typing.
|
|||
|
||||
Use <tt>ocamlc</tt> or <tt>ocamlopt</tt> to compile your
|
||||
SWIG interface like:
|
||||
<p> </p>
|
||||
</p>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
|
|
@ -131,38 +134,47 @@ the user more freedom with respect to custom typing.
|
|||
% ocamlc -c -ccopt "-I/usr/include/foo" example_wrap.c
|
||||
% ocamlc -c example.mli
|
||||
% ocamlc -c example.ml
|
||||
</blockquote>
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<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>
|
||||
|
||||
<blockquote>
|
||||
<pre>% cp example_wrap.cxx example_wrap.cxx.c<br>% ocamlc -c ... -ccopt -xc++ example_wrap.cxx.c<br>% ...<br></pre>
|
||||
</blockquote>
|
||||
<pre>
|
||||
% cp example_wrap.cxx example_wrap.cxx.c<br>% ocamlc -c ... -ccopt -xc++ example_wrap.cxx.c<br>% ...<br>
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<a name="n5"></a><H3>19.1.3 The camlp4 module</H3>
|
||||
<H3><a name="Ocaml_nn5"></a>21.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">
|
||||
</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 -> method ( ... )</td><td>(invoke object) "method" (C_list [ ... ])</td></tr>
|
||||
<tr><td>
|
||||
object <i>'binop</i> argument as in<br>
|
||||
a '+= b</td>
|
||||
|
|
@ -178,9 +190,9 @@ and >>, they are replaced by lsl and lsr in operator names.
|
|||
(invoke a) "!" C_void</td></tr>
|
||||
<tr><td>
|
||||
<b>Smart pointer access like this</b><br>
|
||||
object '-> method ( args )<br>
|
||||
object '-> method ( args )<br>
|
||||
</td><td>
|
||||
(invoke (invoke object "->" C_void))
|
||||
(invoke (invoke object "->" C_void))
|
||||
</td></tr>
|
||||
<tr><td>
|
||||
<b>Invoke syntax</b><br>
|
||||
|
|
@ -211,37 +223,47 @@ let b = C_string (getenv "PATH")
|
|||
</td></tr>
|
||||
</table>
|
||||
|
||||
<a name="n6"></a><H3>19.1.4 Using your module</H3>
|
||||
<H3><a name="Ocaml_nn6"></a>21.1.4 Using your module</H3>
|
||||
|
||||
|
||||
You can test-drive your module by building a
|
||||
<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
|
||||
<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>
|
||||
|
||||
<a name="n7"></a><H3>19.1.5 Compilation problems and compiling with C++</H3>
|
||||
<H3><a name="Ocaml_nn7"></a>21.1.5 Compilation problems and compiling with C++</H3>
|
||||
|
||||
|
||||
As mentioned above, .cxx files need special
|
||||
<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>
|
||||
|
||||
<a name="n8"></a><H2>19.2 The low-level Ocaml/C interface</H2>
|
||||
<H2><a name="Ocaml_nn8"></a>21.2 The low-level Ocaml/C interface</H2>
|
||||
|
||||
|
||||
In order to provide access to overloaded functions, and
|
||||
<p>
|
||||
In order to provide access to overloaded functions, and
|
||||
provide sensible outputs from them, all C entites 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>
|
||||
|
||||
<blockquote><pre>
|
||||
type c_obj =
|
||||
|
|
@ -284,11 +306,15 @@ appropriate C value and returns a c_obj representing it.</li>
|
|||
a C_obj, which contains a closure giving method access.</li>
|
||||
|
||||
</ul>
|
||||
Because of this style, a typemap can return any kind of value it
|
||||
|
||||
<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>
|
||||
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
|
||||
|
|
@ -302,13 +328,15 @@ is that you must append them to the return list with swig_result = caml_list_a
|
|||
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>
|
||||
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.
|
||||
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
|
||||
|
|
@ -316,20 +344,24 @@ is that you must append them to the return list with swig_result = caml_list_a
|
|||
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>
|
||||
|
||||
<a name="n9"></a><H3>19.2.1 The generated module</H3>
|
||||
<H3><a name="Ocaml_nn9"></a>21.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>
|
||||
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">
|
||||
<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
|
||||
|
|
@ -345,11 +377,13 @@ 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>
|
||||
|
||||
<a name="n10"></a><H3>19.2.2 Enums</H3>
|
||||
<H3><a name="Ocaml_nn10"></a>21.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
|
||||
|
|
@ -358,7 +392,8 @@ 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>
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
%module enum_test
|
||||
%{
|
||||
|
|
@ -366,9 +401,11 @@ enum c_enum_type { a = 1, b, c = 4, d = 8 };
|
|||
%}
|
||||
enum c_enum_type { a = 1, b, c = 4, d = 8 };
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
The output mli contains:
|
||||
<p>
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
type c_enum_type = [
|
||||
`unknown
|
||||
|
|
@ -387,7 +424,8 @@ val enum_to_int c_enum_type -> c_obj -> c_obj
|
|||
</blockquote>
|
||||
So it's possible to do this:
|
||||
<blockquote>
|
||||
<pre>bash-2.05a$ ocamlmktop -custom enum_test_wrap.o enum_test.cmo -o enum_test_top
|
||||
<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
|
||||
|
||||
|
|
@ -401,12 +439,10 @@ val x : Enum_test.c_obj = C_enum `a
|
|||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<p> </p>
|
||||
|
||||
<a name="n11"></a><H3>19.2.3 Arrays</H3>
|
||||
<H3><a name="Ocaml_nn11"></a>21.2.3 Arrays</H3>
|
||||
|
||||
|
||||
<a name="n12"></a><H4>19.2.3.1 Simple types of bounded arrays</H4>
|
||||
<H4><a name="Ocaml_nn12"></a>21.2.3.1 Simple types of bounded arrays</H4>
|
||||
|
||||
|
||||
<p>
|
||||
|
|
@ -414,6 +450,7 @@ 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
|
||||
|
|
@ -426,7 +463,7 @@ arrays of simple types with known bounds in your code, but this only works
|
|||
for arrays whose bounds are completely specified.
|
||||
</p>
|
||||
|
||||
<a name="n13"></a><H4>19.2.3.2 Complex and unbounded arrays</H4>
|
||||
<H4><a name="Ocaml_nn13"></a>21.2.3.2 Complex and unbounded arrays</H4>
|
||||
|
||||
|
||||
<p>
|
||||
|
|
@ -439,7 +476,7 @@ 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>
|
||||
|
||||
<a name="n14"></a><H4>19.2.3.3 Using an object</H4>
|
||||
<H4><a name="Ocaml_nn14"></a>21.2.3.3 Using an object</H4>
|
||||
|
||||
|
||||
<p>
|
||||
|
|
@ -453,7 +490,7 @@ Consider writing an object when the ending condition of your array is complex,
|
|||
such as using a required centinel, etc.
|
||||
</p>
|
||||
|
||||
<a name="n15"></a><H4>19.2.3.4 Example typemap for a function taking float * and int</H4>
|
||||
<H4><a name="Ocaml_nn15"></a>21.2.3.4 Example typemap for a function taking float * and int</H4>
|
||||
|
||||
|
||||
<p>
|
||||
|
|
@ -465,11 +502,12 @@ 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"><tr><th><center>tarray.i</center></th></tr>
|
||||
<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>
|
||||
#include <stdio.h>
|
||||
|
||||
void printfloats( float *tab, int len ) {
|
||||
int i;
|
||||
|
|
@ -503,7 +541,7 @@ void printfloats( float *tab, int len );
|
|||
</pre></td></tr></table>
|
||||
|
||||
|
||||
<a name="n16"></a><H3>19.2.4 C++ Classes</H3>
|
||||
<H3><a name="Ocaml_nn16"></a>21.2.4 C++ Classes</H3>
|
||||
|
||||
|
||||
C++ classes, along with structs and unions are represented by C_obj
|
||||
|
|
@ -515,7 +553,8 @@ 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))
|
||||
<table>
|
||||
|
||||
<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>
|
||||
|
|
@ -539,9 +578,8 @@ argument. With zero arguments, the value is returned.
|
|||
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>
|
||||
|
||||
<a name="n17"></a><H4>19.2.4.1 STL vector and string Example</H4>
|
||||
<H4><a name="Ocaml_nn17"></a>21.2.4.1 STL vector and string Example</H4>
|
||||
|
||||
|
||||
Standard typemaps are now provided for STL vector and string. More are in
|
||||
|
|
@ -550,7 +588,8 @@ 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.
|
||||
|
||||
<table border="1" bgcolor="#dddddd"><tr><th><center>example.i</center></th></tr>
|
||||
<table border="1" bgcolor="#dddddd" summary="STL vector and string example">
|
||||
<tr><th><center>example.i</center></th></tr>
|
||||
<tr><td><pre>
|
||||
%module example
|
||||
%{
|
||||
|
|
@ -567,12 +606,17 @@ namespace std {
|
|||
</pre></td></tr>
|
||||
<tr><td><font size="-1"><i>This example is in Examples/ocaml/stl
|
||||
</i></font></td></tr>
|
||||
</table><p>
|
||||
</table>
|
||||
|
||||
Since there's a makefile in that directory, the example is easy to build.<p>
|
||||
<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>
|
||||
|
||||
<blockquote><pre>
|
||||
bash-2.05a$ ./example_top
|
||||
|
|
@ -583,27 +627,27 @@ bash-2.05a$ ./example_top
|
|||
# open Swig ;;
|
||||
# open Example ;;
|
||||
# let x = new_StringVector '() ;;
|
||||
val x : Example.c_obj = C_obj <fun>
|
||||
# x -> ":methods" () ;;
|
||||
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 "~"; C_string "&"; C_string ":parents"; C_string ":classof";
|
||||
C_string ":methods"]
|
||||
# x -> push_back ("foo") ;;
|
||||
# x -> push_back ("foo") ;;
|
||||
- : Example.c_obj = C_void
|
||||
# x -> push_back ("bar") ;;
|
||||
# x -> push_back ("bar") ;;
|
||||
- : Example.c_obj = C_void
|
||||
# x -> push_back ("baz") ;;
|
||||
# x -> push_back ("baz") ;;
|
||||
- : Example.c_obj = C_void
|
||||
# x '[1] ;;
|
||||
- : Example.c_obj = C_string "bar"
|
||||
# x -> set (1,"spam") ;;
|
||||
# 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
|
||||
# for i = 0 to (x -> size() as int) - 1 do
|
||||
print_endline ((x '[i to int]) as string)
|
||||
done ;;
|
||||
foo
|
||||
|
|
@ -613,12 +657,13 @@ baz
|
|||
#
|
||||
</pre></blockquote>
|
||||
|
||||
<a name="n18"></a><H4>19.2.4.2 C++ Class Example</H4>
|
||||
<H4><a name="Ocaml_nn18"></a>21.2.4.2 C++ Class Example</H4>
|
||||
|
||||
|
||||
Here's a simple example using Trolltech's Qt Library:
|
||||
|
||||
<table border="1" bgcolor="#dddddd"><tr><th><center>qt.i</center></th></tr>
|
||||
<table border="1" bgcolor="#dddddd" summary="Qt Library example">
|
||||
<tr><th><center>qt.i</center></th></tr>
|
||||
<tr><td><pre>
|
||||
%module qt
|
||||
%{
|
||||
|
|
@ -638,9 +683,9 @@ public:
|
|||
void resize( int x, int y );
|
||||
void show();
|
||||
};
|
||||
</pre></td></tr></table><p>
|
||||
</pre></td></tr></table>
|
||||
|
||||
<a name="n19"></a><H4>19.2.4.3 Compiling the example</H4>
|
||||
<H4><a name="Ocaml_nn19"></a>21.2.4.3 Compiling the example</H4>
|
||||
|
||||
|
||||
<blockquote><pre>
|
||||
|
|
@ -658,7 +703,7 @@ bash-2.05a$ ocamlmktop -custom swig.cmo -I `camlp4 -where` \
|
|||
-L$QTPATH/lib -cclib -lqt
|
||||
</pre></blockquote>
|
||||
|
||||
<a name="n20"></a><H4>19.2.4.4 Sample Session</H4>
|
||||
<H4><a name="Ocaml_nn20"></a>21.2.4.4 Sample Session</H4>
|
||||
|
||||
|
||||
<blockquote><pre>
|
||||
|
|
@ -670,33 +715,40 @@ bash-2.05a$ ./qt_top
|
|||
# open Swig ;;
|
||||
# open Qt ;;
|
||||
# let a = new_QApplication '(0,0) ;;
|
||||
val a : Qt.c_obj = C_obj <fun>
|
||||
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) ;;
|
||||
val hello : Qt.c_obj = C_obj <fun>
|
||||
# hello -> resize (100,30) ;;
|
||||
- : Qt.c_obj = C_void
|
||||
# hello -> show () ;;
|
||||
# hello -> show () ;;
|
||||
- : Qt.c_obj = C_void
|
||||
# a -> exec () ;;
|
||||
</pre></blockquote><p>
|
||||
# a -> exec () ;;
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
Assuming you have a working installation of QT, you will see a window
|
||||
containing the string "hi" in a button.
|
||||
</p>
|
||||
|
||||
<a name="n21"></a><H3>19.2.5 Director Classes</H3>
|
||||
<H3><a name="Ocaml_nn21"></a>21.2.5 Director Classes</H3>
|
||||
|
||||
|
||||
<a name="n22"></a><H4>19.2.5.1 Director Introduction</H4>
|
||||
<H4><a name="Ocaml_nn22"></a>21.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:
|
||||
<pre><blockquote><p>
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
%module(directors="1")
|
||||
|
||||
...
|
||||
|
|
@ -706,9 +758,9 @@ this:
|
|||
class foo {
|
||||
...
|
||||
};
|
||||
</p></blockquote></pre>
|
||||
</pre></blockquote>
|
||||
|
||||
<a name="n23"></a><H4>19.2.5.2 Overriding Methods in Ocaml</H4>
|
||||
<H4><a name="Ocaml_nn23"></a>21.2.5.2 Overriding Methods in Ocaml</H4>
|
||||
|
||||
|
||||
<p>
|
||||
|
|
@ -721,21 +773,26 @@ underlying implemenation. 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>
|
||||
</p>
|
||||
|
||||
<a name="n24"></a><H4>19.2.5.3 Director Usage Example</H4>
|
||||
<H4><a name="Ocaml_nn24"></a>21.2.5.3 Director Usage Example</H4>
|
||||
|
||||
|
||||
<table border="1" bgcolor="#dddddd"><tr><th><center>example_prog.ml</center>
|
||||
<table border="1" bgcolor="#dddddd" summary="Director usage example">
|
||||
<tr><th><center>example_prog.ml</center>
|
||||
</th></tr>
|
||||
<tr><td><pre>
|
||||
open Swig
|
||||
|
|
@ -745,14 +802,14 @@ open Example
|
|||
|
||||
let triangle_class pts ob meth args =
|
||||
match meth with
|
||||
"cover" ->
|
||||
"cover" ->
|
||||
(match args with
|
||||
C_list [ x_arg ; y_arg ] ->
|
||||
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 ;;
|
||||
| _ -> raise (Failure "cover needs two double arguments."))
|
||||
| _ -> (invoke ob) meth args ;;
|
||||
|
||||
let triangle =
|
||||
new_derived_object
|
||||
|
|
@ -763,6 +820,7 @@ let triangle =
|
|||
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.
|
||||
|
|
@ -776,27 +834,31 @@ 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 (<tt> </tt>) between
|
||||
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>
|
||||
<a name="n25"></a><H4>19.2.5.4 Creating director objects</H4>
|
||||
</p>
|
||||
|
||||
<H4><a name="Ocaml_nn25"></a>21.2.5.4 Creating director objects</H4>
|
||||
|
||||
|
||||
The definition of the actual object triangle can be described this way:
|
||||
<pre><blockquote><p>
|
||||
<blockquote><pre>
|
||||
let triangle =
|
||||
new_derived_object
|
||||
new_shape
|
||||
(triangle_class ((0.0,0.0),(0.5,1.0),(1.0,0.0)))
|
||||
'()
|
||||
</p></blockquote></pre>
|
||||
</pre></blockquote>
|
||||
|
||||
<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
|
||||
|
|
@ -806,6 +868,8 @@ 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
|
||||
|
|
@ -819,8 +883,9 @@ 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>
|
||||
|
||||
<a name="n26"></a><H4>19.2.5.5 Typemaps for directors, <tt>directorin, directorout, directorargout</tt></H4>
|
||||
<H4><a name="Ocaml_nn26"></a>21.2.5.5 Typemaps for directors, <tt>directorin, directorout, directorargout</tt></H4>
|
||||
|
||||
|
||||
<p>
|
||||
|
|
@ -829,8 +894,9 @@ 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>
|
||||
<a name="n27"></a><H4>19.2.5.6 <tt>directorin</tt> typemap</H4>
|
||||
</p>
|
||||
|
||||
<H4><a name="Ocaml_nn27"></a>21.2.5.6 <tt>directorin</tt> typemap</H4>
|
||||
|
||||
|
||||
<p>
|
||||
|
|
@ -841,7 +907,7 @@ code receives when you are called. In general, a simple <tt>directorin</tt> typ
|
|||
can use the same body as a simple <tt>out</tt> typemap.
|
||||
</p>
|
||||
|
||||
<a name="n28"></a><H4>19.2.5.7 <tt>directorout</tt> typemap</H4>
|
||||
<H4><a name="Ocaml_nn28"></a>21.2.5.7 <tt>directorout</tt> typemap</H4>
|
||||
|
||||
|
||||
<p>
|
||||
|
|
@ -852,11 +918,11 @@ for the same type, except when there are special requirements for object
|
|||
ownership, etc.
|
||||
</p>
|
||||
|
||||
<a name="n29"></a><H4>19.2.5.8 <tt>directorargout</tt> typemap</H4>
|
||||
<H4><a name="Ocaml_nn29"></a>21.2.5.8 <tt>directorargout</tt> typemap</H4>
|
||||
|
||||
|
||||
<p>
|
||||
C++ allows function arguments which are by pointer (*) and by reference (&)
|
||||
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
|
||||
|
|
@ -869,7 +935,7 @@ 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>
|
||||
|
||||
<a name="n30"></a><H3>19.2.6 Exceptions</H3>
|
||||
<H3><a name="Ocaml_nn30"></a>21.2.6 Exceptions</H3>
|
||||
|
||||
|
||||
Catching exceptions is now supported using SWIG's %exception feature. A simple
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue