Added dynamic targets to example makefiles Added ocaml_dynamic and ocaml_dynamic_cpp targets to Examples/Makefile.in Added OCAMLFIND and OCAMLDLGEN AC_SUBST lines in configure.in Currently, dynamic linking relies on ocamlfind and Gerd Stolpmann's Dl package, as well as some tricky elf linking. git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@4413 626c5289-ae23-0410-ae9c-e8d60b6d4f22
587 lines
No EOL
22 KiB
HTML
587 lines
No EOL
22 KiB
HTML
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
|
<html>
|
|
<head>
|
|
<title>SWIG and Ocaml</title>
|
|
|
|
</head>
|
|
<body bgcolor="#ffffff">
|
|
<a name="n1"></a>
|
|
<a name="n1"></a><H1>16 SWIG and Ocaml</H1>
|
|
<!-- INDEX -->
|
|
<ul>
|
|
<li><a href="#n2">Preliminaries</a>
|
|
<ul>
|
|
<li><a href="#n3">Running SWIG</a>
|
|
<li><a href="#n4">Getting the right header files</a>
|
|
<li><a href="#n5">Compiling the code</a>
|
|
<li><a href="#n6">The camlp4 module</a>
|
|
<li><a href="#n7">Current thoughts on best practice for Ocaml</a>
|
|
<li><a href="#n8">Using your module</a>
|
|
<li><a href="#n9">Compilation problems and compiling with C++</a>
|
|
</ul>
|
|
<li><a href="#n10">The low-level Ocaml/C interface</a>
|
|
<ul>
|
|
<li><a href="#n11">The generated module</a>
|
|
<li><a href="#n12">Enums</a>
|
|
<li><a href="#n13">C++ Classes</a>
|
|
<ul>
|
|
<li><a href="#n14">STL vector and string Example</a>
|
|
<li><a href="#n15">C++ Class Example</a>
|
|
<li><a href="#n16">Compiling the example</a>
|
|
<li><a href="#n17">Sample Session</a>
|
|
</ul>
|
|
<li><a href="#n18">Exceptions</a>
|
|
</ul>
|
|
</ul>
|
|
<!-- INDEX -->
|
|
|
|
|
|
|
|
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 sophistocated 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 repetetive 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.
|
|
|
|
<a name="n2"></a><H2>16.1 Preliminaries</H2>
|
|
|
|
|
|
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 (m68k,MIPS,Intel) 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.
|
|
|
|
<a name="n3"></a><H3>16.1.1 Running SWIG</H3>
|
|
|
|
|
|
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.
|
|
|
|
<blockquote>
|
|
<pre>%swig -ocaml example.i</pre>
|
|
</blockquote>
|
|
|
|
<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>
|
|
|
|
<a name="n4"></a><H3>16.1.2 Getting the right header files</H3>
|
|
|
|
|
|
You may need the libswigocaml.h file that comes with the
|
|
distribution to be included. It provides several useful functions
|
|
that almost all programs that use SWIG will need. It is located in
|
|
$(prefix)/include/libswigocaml.h where $(prefix) is usually /usr/local,
|
|
but could be /usr. This is set at configure time. The functions most
|
|
frequently used in here are isnull and nullptr for creating and checking
|
|
null pointers.
|
|
|
|
<a name="n5"></a><H3>16.1.3 Compiling the code</H3>
|
|
|
|
|
|
Use <tt>ocamlc</tt> or <tt>ocamlopt</tt> to compile your
|
|
SWIG interface like:
|
|
<p> </p>
|
|
|
|
<blockquote>
|
|
<pre>% ocamlc -c -ccopt "-I/usr/include/foo -I/usr/local/include" example_wrap.c<br>% ocamlc -c example.mli<br>% ocamlc -c example.ml<br></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>
|
|
|
|
<a name="n6"></a><H3>16.1.4 The camlp4 module</H3>
|
|
|
|
|
|
The camlp4 module (swig.ml -> swig.cmo) contains a simple rewriter which
|
|
makes C++ code blend more seamlessly with objective caml code. It's use is
|
|
optional. The source file is included in the Lib/ocaml directory of the
|
|
SWIG source distribution.
|
|
<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>
|
|
Here are the main rewriting rules:
|
|
<p>
|
|
<table border="1">
|
|
<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>
|
|
object '-> "method" ( args )
|
|
</td><td>
|
|
(invoke (invoke object "->" C_void))
|
|
</td></tr>
|
|
<tr><td>
|
|
<b>Invoke syntax</b>
|
|
object . '( ... )
|
|
</td><td>
|
|
(invoke object) "()" (C_list [ ... ])
|
|
</td></tr>
|
|
<tr><td>
|
|
<b>Array syntax</b>
|
|
object '[ 10 ]
|
|
</td><td>
|
|
(invoke object) "[]" (C_int 10)
|
|
</td></tr>
|
|
</table>
|
|
|
|
<a name="n7"></a><H3>16.1.5 Current thoughts on best practice for Ocaml</H3>
|
|
|
|
|
|
Because the VC compiler (cl) needs link options specified
|
|
after all compiler options, and ocamlc doesn't really understand
|
|
that, I think that this is the best way to link ocaml code with C++
|
|
code. I formulated this method to make it easy for co-workers who
|
|
rely on MSDev to create GUIs, etc.. to live in harmony with the
|
|
ocaml parts of the application.
|
|
|
|
<p> Let's say you have ocaml sources foo.ml and bar.ml and interface frob.i;
|
|
</p>
|
|
|
|
<blockquote><pre>
|
|
swig -ocaml -c++ frob.i
|
|
ocamlc -custom -c frob.mli
|
|
ocamlc -custom -c frob.ml
|
|
cp frob_wrap.cxx frob_wrap.c
|
|
ocamlc -custom -c -I$(FROBLIB)/include frob_wrap.c
|
|
ocamlc -custom -c foo.ml
|
|
ocamlc -custom -c bar.ml
|
|
ocamlc -pack -o foobar.cmo foo.cmo bar.cmo frob.cmo
|
|
ocamlc -custom -output-obj -o foobar.obj foobar.cmo
|
|
</pre></blockquote>
|
|
|
|
<p> At this point, foobar.obj can be included in your MSVC project and
|
|
linked against other code. This is how you link it: </p>
|
|
|
|
<blockquote><pre>
|
|
link /OUT:big_program.exe \
|
|
other1.obj other2.obj foobar.obj frob_wrap.obj \
|
|
$(OCAMLLIB)/ocamlrun.lib $(FROBLIB)/lib/frob.lib
|
|
</pre></blockquote>
|
|
|
|
<a name="n8"></a><H3>16.1.6 Using your module</H3>
|
|
|
|
|
|
You can test-drive your module by building a
|
|
toplevel ocaml interpreter. Consult the ocaml manual for details.
|
|
|
|
<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.
|
|
|
|
<a name="n9"></a><H3>16.1.7 Compilation problems and compiling with C++</H3>
|
|
|
|
|
|
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.
|
|
|
|
<a name="n10"></a><H2>16.2 The low-level Ocaml/C interface</H2>
|
|
|
|
|
|
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>
|
|
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>
|
|
|
|
<blockquote><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></blockquote>
|
|
A few functions exist which generate and return these:<br>
|
|
|
|
<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>
|
|
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>
|
|
|
|
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 interchangable 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>
|
|
|
|
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>
|
|
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.
|
|
|
|
<a name="n11"></a><H3>16.2.1 The generated module</H3>
|
|
|
|
|
|
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>
|
|
|
|
You can introduce extra code into the output wherever you like with SWIG.
|
|
These are the places you can introduce code:
|
|
<table border="1">
|
|
<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>
|
|
</table>
|
|
|
|
<a name="n12"></a><H3>16.2.2 Enums</H3>
|
|
|
|
|
|
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>
|
|
<blockquote><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></blockquote>
|
|
<p>
|
|
The output mli contains:
|
|
<p>
|
|
<blockquote><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>
|
|
</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
|
|
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>
|
|
</blockquote>
|
|
|
|
<p> </p>
|
|
|
|
<a name="n13"></a><H3>16.2.3 C++ Classes</H3>
|
|
|
|
|
|
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))
|
|
<table>
|
|
<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>":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>
|
|
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="n14"></a><H4>16.2.3.1 STL vector and string Example</H4>
|
|
|
|
|
|
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.
|
|
|
|
<table border="1" bgcolor="#dddddd"><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>
|
|
Here's a sample transcript of an interactive session using a string vector
|
|
after making a toplevel like this:
|
|
<pre>ocamlmktop -custom -cclib -g -ccopt -g -g \
|
|
example_wrap.o example.cmo -o example_top -cclib -lstdc++
|
|
</pre><p>
|
|
<blockquote><pre>
|
|
bash-2.05a$ ./example_top
|
|
Objective Caml version 3.06
|
|
|
|
# open Example ;;
|
|
# let x = new_StringVector C_void ;;
|
|
val x : Example.c_obj = C_obj <fun>
|
|
# (invoke x) ":methods" C_void ;;
|
|
- : 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"]
|
|
# (invoke x) "push_back" (C_string "foo") ;;
|
|
- : Example.c_obj = C_void
|
|
# (invoke x) "push_back" (C_string "bar") ;;
|
|
- : Example.c_obj = C_void
|
|
# (invoke x) "push_back" (C_string "baz") ;;
|
|
- : Example.c_obj = C_void
|
|
# (invoke x) "[]" (C_int 1) ;;
|
|
- : Example.c_obj = C_string "bar"
|
|
# (invoke x) "set" (C_list [ C_int 1 ; C_string "spam" ]) ;;
|
|
- : Example.c_obj = C_void
|
|
# (invoke x) "[]" (C_int 1) ;;
|
|
- : Example.c_obj = C_string "spam"
|
|
#
|
|
</pre></blockquote>
|
|
|
|
<a name="n15"></a><H4>16.2.3.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>
|
|
<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><p>
|
|
|
|
<a name="n16"></a><H4>16.2.3.3 Compiling the example</H4>
|
|
|
|
|
|
<blockquote><pre>
|
|
bash-2.05a$ QTPATH=/your/qt/path
|
|
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 qt_wrap.o qt.cmo -o qt_top -cclib -L$QTPATH/lib -cclib -lqt
|
|
</pre></blockquote>
|
|
|
|
<a name="n17"></a><H4>16.2.3.4 Sample Session</H4>
|
|
|
|
|
|
<blockquote><pre>
|
|
bash-2.05a$ ./qt_top
|
|
Objective Caml version 3.06
|
|
|
|
# open Qt ;;
|
|
# let a = new_QApplication (C_list [ C_int 0; C_int 0 ]) ;;
|
|
val a : Qt.c_obj = C_obj <fun>
|
|
# let hello = new_QPushButton (C_list [ C_string "hi" ; C_int 0 ]) ;;
|
|
val hello : Qt.c_obj = C_obj <fun>
|
|
# (invoke hello) "resize" (C_list [ C_int 100 ; C_int 30 ]) ;;
|
|
- : Qt.c_obj = C_void
|
|
# (invoke hello) "show" C_void ;;
|
|
- : Qt.c_obj = C_void
|
|
# (invoke a) "exec" C_void ;;
|
|
</pre></blockquote><p>
|
|
|
|
Or with the camlp4 module:
|
|
|
|
<blockquote><pre>
|
|
bash-2.05a$ ./qt_top
|
|
Objective Caml version 3.06
|
|
|
|
# #load "camlp4o.cma" ;;
|
|
Camlp4 Parsing version 3.06
|
|
|
|
# #load "./swig.cmo" ;;
|
|
# 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></blockquote><p>
|
|
|
|
In either case, assuming you have a working installation of QT, you will
|
|
see a window containing the string "hi" in a button.
|
|
|
|
<a name="n18"></a><H3>16.2.4 Exceptions</H3>
|
|
|
|
|
|
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.
|
|
</body>
|
|
</html> |