O'Jacaré - User's manual
Date: 2004/06/01 15:07:00
Emmanuel Chailloux - Grégoire Henry
Table of Contents
1 Overview
O'Jacaré is a new code generator to interoperate between Java
and Objective Caml
through their object model.
O'Jacaré is an strongly-typed object-interface based on the camljava
library by Xavier Leroy.
O'Jacaré defines a basic Interface Definition Language (IDL) for classses and interfaces description, and provides a code-generator for mapping Java classes directly to O'Caml classes.
O'Jacaré generates all needed wrapper classes and enables static typechecking in both worlds.
Although the IDL is an intersection from these two object models, O'Jacaré allows to combine features from both.
2 Installation
O'Jacaré distribution is available from http://www.pps.jussieu.fr/~henry/ojacare/.
2.1 Requirements
You should also have installed O'Caml (http://caml.inria.fr/)
and a Java SDK.
O'Jacaré depends on the library camljava from Xavier Leroy.
It's available from http://pauillac.inria.fr/~xleroy/software.html#camljava.
But a small patch is needed before using it with O'Jacaré (mainly for threading difficulties).
Next section will explain how to install camljava for using with O'Jacaré.
2.2 The camljava library
The camljava library has been compiled on:
-
Linux i386 with Sun's JDK 1.4.2
- Mac OS X 10.2 and 10.3 with Apple's JDK 1.3.1
- Windows with MinGW via cygwin and Sun's JDK 1.4.2
Default Makefile are for Linux.
Use make -f Makefile.osx (resp. make -f Makefile.mingw) and
Makefile.config.osx (resp. Makefile.config.mingw)
instead of make and Makefile.config in the following if you are
using Mac OS X (resp. MinGW via cygwin).
-
Download camljava
-
Direct download link is http://caml.inria.fr/distrib/bazar-ocaml/camljava-0.2.tar.gz.
- Uncompress the distribution
- Once camljava-O.2 download to the toplevel directory of the O'Jacaré distribution, do:
tar -xzf camljava-0.2.tar.gz
- Patch it
-
The patch is available in the O'Jacaré distribution.
From the top directory do :
patch -p0 < camljava-0.2.diff
- Configure the system
-
Edit the file Makefile.config to adjust it to your current installation of Java SDK (This is the critical part).
- Build it
-
First, build it with the byte-code compiler. From the top directory do :
If wanted, you can build it with the native compiler. From the top directory do :
- Install it
-
You could have to become super-user before running this command. From the top directory do :
- Test the installation
-
You can give your installation a small test (output should be self-explanatory).
- Clean directories
-
Installation is complete. Time to clean up:
2.3 O'Jacaré
O'Jacaré is available on the same platforms than the camljava library.
-
Configure the system
-
Edit the file Makefile.config to adjust it to your current installation of O'Caml and camljava.
- Build it
-
First build it with the byte-code compiler. From the toplevel directory, do:
make -C src depend
make -C src byte
If wanted, you can build it with the native compiler. From the toplevel directory, do:
- Install it
-
You could have to become super-user before running this command. From the toplevel directory, do:
- Test the installation
-
Next section (3.2) could be considered as a test to your installation.
- Clean directories
-
Installation is complete. Time to clean up:
3 Compiling with O'Jacaré
3.1 Principle
The tool ojacare take as only argument the IDL file to process,
and generate from it:
-
an O'Caml module (.mli and .ml) named as the IDL file ;
- as many Java classes, as classes with callback attribute in the IDL file.
Thay are generated in a directory callback and named by prefixing with callback their original package hierarchy.
The generated O'Caml module must be compiled with parameters -I +camljava -I +ojacare (if you choose default installation directory for both camljava and O'Jacaré).
The generated Java classes must be compiled with `ocamlc -where`/camljava/camljava.jar in you CLASSPATH (if you choose default installation directory for camljava)
Main must be linked with the jni.cma and jnihelpers.cma archives, found respectively in camljava and O'Jacaré installation directory. (Use -I +camljava jni.cma -I +ojacare jnihelpers.cma parameters as default.)
O'Jacaré provides a simple generic Makefile, see 6.4.3.
3.2 Full example
Note:
After editing the file
examples/Makefile.config,
the following command in directory
examples/point/ will build the example as detailed in this section.
Let's use from O'Caml three Java classes : Point, ColoredPoint, and Cloud (filled with Point).
In a second step, we want to specialize within O'Caml the class ColoredPoint (by using callback mechanism).
The three Java classes are supposed to be implemented within a package mypack and describe in file p.idl (see 6.4.1).
Process p.idl file with:
It will generate three files:
-
p.ml : O'Caml wrapper's ;
- p.mli : signature ;
- callback/mypack/ColoredPoint.java : subclass of mypack.ColoredPoint for callback mechanism.
They can also be compiled:
$ ocamlc -I +camljava -I +ojacare p.mli
$ ocamlc -I +camljava -I +ojacare p.ml
$ javac -classpath "`ocamlc -where`/camljava/camljava.jar:." callback/mypack/ColoredPoint.java
Finally, taking main-point.ml as main file (6.4.2), everything can be linked:
$ ocamlc -I +camljava -I +ojacare main-point.ml
$ ocamlc -I +camljava -I +ojacare -o point jni.cma jnihelpers.cma p.cmo main-point.cmo
You can now execute ./point.
O'Jacaré can also be used from toplevel:
$ ocamlmktop -o ocaml-point -I +camljava -I +ojacare jni.cma jnihelpers.cma p.cmo
$ ./ocaml-point -I +ojacare
Objective Caml version 3.07+2
#
3.3 More examples
Examples in this section are available in the directory examples/ from the O'Jacaré distribution (see section 2).
Note:
After editing the file
examples/Makefile.config, following commands can be used in each sub-directory.
Building with bytecode compiler, then running it:
Building with native version, then running it:
Building a custom toplevel, then running it:
make toplevel
make run-toplevel
-
point
- Simple example with in-heritance and late-binding
- rectangle
- Multiple in-heritance in O'Caml from encapsulated Java classes
- observer
- Design-patterns
-
Model in Java; Observer in O'Caml
- How to simulate main in Java with static method
- visitorML
- Design-patterns
-
Model in Java; Visitor in O'Caml
- visitorJava
- Visit with Java a recursive O'Caml value
- ojDvi
- a DVI viewer
-
based on mldvi from Alexandre Miquel: http://pauillac.inria.fr/~miquel/
- minimalist GUI with AWT
- awt
- let's try building an GUI interactively from toplevel
4 IDL description
This section first describes the whole syntax of IDL.
It could be read as a subset of the Java syntax with some attributes specified between brackets
(name aliasing, callback mechanism, ...).
Second part explains, from an user point of view, the code generated by ojacare.
4.1 Syntax
| file |
::= |
package [package]* |
| |
| |
decl [decl]* |
| |
| package |
::= |
package qname ; decl [decl]* |
| decl |
::= |
class |
| |
| |
interface |
| |
| class |
::= |
[ [attributes] ] [abstract] class name |
| |
|
[ extends qname ] |
| |
|
[ implements qname [, qname]* ] |
| |
|
{ |
| |
|
[class_elt ;]* |
| |
|
} |
| class_elt |
::= |
[ [attributes] ] [static] [final] type name |
| |
| |
[ [attributes] ] [static] [abstract] type name ([args]) |
| |
| |
[attributes] <init> ([args]) |
| |
| interface |
::= |
[ [attributes] ] interface name |
| |
|
[ extends qname [, qname]* ] |
| |
|
{ |
| |
|
[interface_elt ;]* |
| |
|
} |
| interface_elt |
::= |
[ [attributes] ] type name |
| |
| |
[ [attributes] ] type name ([args]) |
| |
| args |
::= |
arg [, arg]* |
| arg |
::= |
[ [attributes] ] type [name] |
| |
| attributes |
::= |
attribute [, attribute]* |
| attribute |
::= |
name ident |
| |
| |
callback |
| |
| |
array |
| |
| type |
::= |
basetype |
| |
| |
object |
| |
| |
basetype [ ] |
| basetype |
::= |
void |
| |
| |
boolean |
| |
| |
byte |
| |
| |
char |
| |
| |
short |
| |
| |
int |
| |
| |
long |
| |
| |
float |
| |
| |
double |
| |
| |
string |
| object |
::= |
qname |
| |
| qname |
::= |
name [. name]* |
| name |
::= |
ident |
Figure 1 presents type correspondence for base-type.
| Java |
IDL |
O'Caml |
| boolean |
boolean |
bool |
| byte |
byte |
int |
| char |
char |
int |
| short |
short |
int |
| int |
int |
int |
| long |
long |
int64 |
| float |
float |
float |
| double |
double |
float |
| java.lang.String |
string |
string |
Figure 1: Base-type correspondance
A contrario, class type are shared,
and there are 2 different mappings for arrays
(specified by attribute array).
| Java |
IDL |
O'Caml |
| type [] |
type [] |
type JniArray.jArray |
| [array] type [] |
type [] |
type array |
Figure 2: Array type correspondance
Class ['a] JniArray.jArray allows array sharing between O'Caml and Java (see sections 5.1.5 and 5.1.6 for furthers details).
4.3 Generated code
Package
As there is no import mechanism now in O'Jacaré,
you can describe multiple package in one file.
package java.util;
// some classes from package java.util
package mypack;
// some classes from package mypack
They indicate where to find Java classes,
but there is only one generated O'Caml module.
It's named as the IDL file.
Class, abstract class, interface
IDL, as Java, allows class, abstract class and interface description.
package java.util;
class Object {
// constructors, methods, fields, static methods, static fields
}
interface Iterator {
// methods, static fields
}
abstract class AbstractCollection {
// constructors, methods, fields, static methods, static fields
}
O'Jacaré will generate three class type : jObject, jIterator, jAbstractCollection.
When you describe two classes with the same name in different package,
or when you're unhappy with automatic naming,
you must use name aliasing :
package java.awt;
class Color {
// ...
}
package mypack;
[name jMyColor] class Color {
// ...
}
O'Jacaré will generate two class type : jColor, jMyColor.
O'Jacaré introduces class-type JniHierarchy.jTop,
subtype of every generated class-type.
class type jTop =
object
method _get_jniobj: Jni.obj
end
For type safety, O'Jacaré generates abstract type for JNI reference (Jni.obj) : _jni_jColor, _jni_jMyColor, ...
class type jColor =
object
inherit JniHierarchy.top
method _get_jni_jColor : _jni_jColor
(* ... *)
end
class type jMyColor =
object
inherit JniHierarchy.top
method _get_jni_jMyColor : _jni_jMyColor
(* ... *)
end
Method and field
package mypack;
class Point {
int x;
final string name;
void rMoveTo(int);
[name to_string] string toString();
}
class Cloud {
Point getPoint();
}
For a field, O'Jacaré will generate accessors and modifiers methods in class type.
When attribute final is specified, only accessors will be generated.
class type jPoint =
object
inherit JniHierarchy.top
method _get_jni_jPoint : _jni_jPoint
method get_x: unit -> int
method set_x: int -> unit
method get_name: unit -> string
method rMoveTo: int -> unit
method to_string: unit -> string
end
When class type appears in a method from IDL,
signature in O'Caml will use the generated class type.
class type jCloud =
object
inherit JniHierarchy.top
method _get_jni_jCloud : _jni_jCloud
method getPoint: unit -> jPoint
end
O'Jacaré generates encapsulation / unencapsulation code within method code.
Constructor
Constructors are named <init> (in reference to JNI).
package java.util;
class Date {
[name current_date] <init>();
[name date_with_seconds] <init>(long date);
}
Name alias are mandatory for constructor (no overloading in O'Caml).
O'Jacaré will generate an O'Caml class for each constructor in IDL.
class date_with_seconds : int64 -> jDate
class current_date : unit -> jDate
Static method and field
O'Jacaré accept static field, and static method description.
package java.awt;
class Color {
static final Color blue;
[name yellow] static final Color yellow;
}
Static methods and fields are mapped to global declarations.
O'Jacaré prefix their name with qualified class name, unless you specify a name alias.
val java_awt_jColor__get_blue : unit -> jColor
val get_yellow : unit -> jColor
Inheritance
Sub-typing of class-type generated with O'Jacaré reflect sub-classing in IDL.
package mypack;
class Point {
int x; int y;
[name point] <init>(int, int);
void moveTo(int, int);
}
interface Colored {
string getColor();
void setColor(string);
}
class ColoredPoint extends Point implements Colored {
[name colored_point] <init>
[name eq_colored_point] eq(ColoredPoint);
}
For class ColoredPoint, O'Jacaré will generate this class type:
class type jColoredPoint =
object
inherit jPoint
inherit jColored
method _get_jni_jColoredPoint : _jni_jColoredPoint
method eq_colored_point : jColoredPoint -> bool
end
Dynamic downcast mechanism of Java for encapsulated object is available through generated functions.
val jColoredPoint_of_top : JniHierarchy.top -> jColoredPoint
Callback attribut with class
Until now, O'Jacaré generates encapsulation code for Java classes (wrapper).
I.e. calling in Java a method upon this, stay in Java's world.
O'Jacaré can take advantage of callback mechanism from camljava with the callback attribute.
package mypack;
// ...
[callback] class ColoredPoint extends Point implements Colored {
[name colored_point] <init>(int, int, string);
[name default_colored_point] <init>();
// ...
}
O'Jacaré will generate one Java subclass to mypack.ColoredPoint named callback.mypack.ColoredPoint.
It override each method with a callback to O'Caml equivalent.
O'Jacaré will generate two new stub classes in O'Caml (in general, as many stub as constructor in IDL).
class virtual _stub_colored_point :
int -> int -> string -> _stub_jColoredPoint
class virtual _stub_default_colored_point : unit -> _stub_jColoredPoint
Both Java and O'Caml generated class contains a reference to the other one.
Sub-classing the stub, will allow late-binding between the two host languages.
Callback attribute with interface
The callback attribute, can also be used with interface.
As there is no constructor for interface,
O'Jacaré will generate only one stub in O'Caml with no argument.
There is still one generated Java class.
4.4 Exception
Exceptions raised by Java are encapsulated by camljava into an O'Caml exception (Jni.Exception of Jni.obj).
5 Programming with O'Jacaré
5.1 Usage from O'Caml
Example in this section are executed in a toplevel build after processing p.idl (6.4.1) with ojacare.
$ ocamlmktop -o ocaml-point -I +camljava -I +ojacare jni.cma jnihelpers.cma p.cmo
$ ./ocaml-point -I +ojacare
Objective Caml version 3.07+2
#
5.1.1 Objects allocation
# let p = new point 3 4;;
val p : P.point = <obj>
# let cp = new colored_point 2 5 "vert";;
val cp : P.default_colored_point = <obj>
# let c = new empty_cloud;;
val c : unit -> P.empty_cloud = <fun>
5.1.2 Method calls
With base-type:
# p#toString ();;
- : string = "(3,4)"
# cp#toString ();;
- : string = "(2,5):vert"
With object as argument:
# c#addPoint p;;
- : unit = ()
# c#addPoint (pc :> jPoint);;
- : unit = ()
# c#toString ();;
- : string = "[(3,4), (2,5):vert]"
Accepted:
# let p2 = (new colored_point 3 5 "bleu" :> jPoint);;
val p2 : P.jPoint = <obj>
# jColoredPoint_of_top (p2 :> JniHierarchy.top);;
- : P.jColoredPoint = <obj>
Rejected:
# jColoredPoint_of_top (p :> JniHierarchy.top);;
Exception: Failure "``cast error'' : jColoredPoint (mypack/ColoredPoint)".
5.1.4 Class specialization
By subclassing the generated stub:
# class spec_colored_point x y c =
object
inherit _stub_colored_point x y c as super
method getColor () = "Caml"^(super#getColor ())
end;;
class spec_colored_point : int -> int -> string -> object ... end
# let spc = new spec_colored_point 2 3 "bleu";;
val spc : spec_colored_point = <obj>
# spc#toString ();;
- : string = "(2,3):Camlbleu"
Warning, when subclassing the wrapper, don't expect late-binding:
# class spec_colored_point x y c =
object
inherit colored_point x y c as super
method getColor () = "Caml"^(super#getColor ())
end;;
class false_spec_colored_point : int -> int -> string -> object ... end
# let fspc = new false_spec_colored_point 2 3 "bleu";;
val fspc : false_spec_colored_point = <obj>
# fspc#toString ();;
- : string = "(2,3):bleu"
5.1.5 Arrays by sharing
Array type in IDL are shared.
They are manipulated through a class defined in module JniArray.
class type ['a] jArray =
object
method _get_jniobj : Jni.obj
method get : int -> 'a
method set : int -> 'a -> unit
end
When using array type in IDL:
package java.lang;
class String {
char[] toCharArray();
}
O'Jacaré will generate this class type:
class type jString =
object
inherit JniHierarchy.top
method _get_jni_jString : _jni_jString
method toCharArray : unit -> int JniArray.jArray
end
The module JniArray, provide way to initializing array from base type :
val init_boolean_jArray : int -> (int -> bool) -> bool jArray
(* ... *)
val init_double_jArray : int -> (int -> float) -> float jArray
val init_string_jArray : int -> (int -> string) -> string jArray
val init_top_jArray :
int -> (int -> JniHierarchy.top) -> JniHierarchy.top jArray
For each class in IDL, O'Jacaré will generate an array initializer.
val jArray_init_jString : int -> (int -> jString) -> jString JniArray.jArray
5.1.6 Arrays by copy
O'Jacaré offers a mechanism for converting Java array to O'Caml arrays.
package java.lang;
class String {
[array] char[] toCharArray();
}
The attribute array before char[], convert int JniArray.jArray to int array.
class type jString =
object
inherit JniHierarchy.top
method _get_jni_jString : _jni_jString
method toCharArray : unit -> int array
end
5.2 Usage from Java
O'Jacaré was first for using Java from O'Caml.
But there is some tips with callback mechanism for using it from Java.
5.2.1 Describing O'Caml classes
Starting with some O'Caml class.
class mlclass =
object
(* methods, ... *)
end
You must then describe it with an interface in Java and a callback interface in IDL.
[callback] interface MlClass {
// methods, ...
}
Then implements bindings O'Caml class.
class interface_mlclass =
object
inherit mlclass
inherit _stub_jMlClass ()
end
5.2.2 Simulating main in Java
Describe static main method in IDL.
class MainJava {
[name main_java] static void main(string []);
}
Converting argv and then calling Java main from O'Caml.
let _ =
let argv =
JniArray.init_string_jArray (Array.length Sys.argv) (fun i -> Sys.argv.(i))
in
main_java argv
5.2.3 Objects allocation
Description in IDL:
[callback] interface SomeMlClass {
// ...
}
[callback] interface MainML {
SomeMLClass create();
// ...
}
class MainJava {
[name main_java] static void main(string [], MainML);
}
O'Caml implementation:
class main_ml =
object
method create () = new some
(* ... *)
end
let _ =
let argv =
JniArray.init_string_jArray (Array.length Sys.argv) (fun i -> Sys.argv.(i))
in
main_java argv (new main_ml)
6 Appendices
6.1 Common errors
Take care of classpath, or expect the following message:
Fatal error: exception Failure("Class not found : mypack.Point.")
If your IDL is not in sync with class file at execution time, expect the following error:
Fatal error: exception Failure("Unknown method from IDL in class "mypack.Point" : "double distance()".")
6.2 Known problems
-
Threading
- Communications between O'Caml and Java should be restrained to the main thread.
- GC
- Callback objects are never deallocated.
6.3 Underlying library camljava
6.3.1 Presentation
Quoting README from Xavier Leroy:
Caml/C interface JNI (Java Native Interface)
Caml <------------------> C <-----------------------------> Java
Currently, CamlJava provides a low-level, weakly-typed OCaml interface
very similar to the JNI. Java object references are mapped to an
abstract type, and various JNI-like operations are provided to allow
Java method invocation, field access, and more. A basic callback
facility (allowing Java code to invoke methods on Caml objects) is
also provided, although some stub Java code must be written by hand.
A good knowledge of the JNI is assumed; see Sun's
JNI book or http://java.sun.com/products/jdk/1.2/docs/guide/jni/
Then, the comments in lib/jni.mli should make sense.
This library contains:
-
an O'Caml module : Jni ;
- and a minimal Java package fr.inria.caml.camljava for callback.
It impose a entry point in O'Caml : linking a program with jni.cma will initialize JVM at startup.
Examples in this section are built in an unique toplevel session:
ocamlmktop -o ocamljava -I +camljava jni.cma
./ocamljava -I +camljava
Introspection
# let class_frame = Jni.find_class "java/awt/Frame";;
val class_frame : Jni.clazz = <abstr>
# let class_button = Jni.find_class "java/awt/Button";;
val class_button : Jni.clazz = <abstr>
# let m_frame_pack = Jni.get_methodID class_frame "pack" "()V";;
val m_frame_pack : Jni.methodID = <abstr>
# let m_frame_show = Jni.get_methodID class_frame "show" "()V";;
val m_frame_show : Jni.methodID = <abstr>
Allocation and initialization
# let f = Jni.alloc_object class_frame;;
val f : Jni.obj = <abstr>
# let b = Jni.alloc_object class_button;;
val b : Jni.obj = <abstr>
# let m_frame_init = Jni.get_methodID class_frame "<init>" "(Ljava/lang/String;)V";;
val m_frame_init : Jni.methodID = <abstr>
# let m_button_init = Jni.get_methodID class_button "<init>" "(Ljava/lang/String;)V";;
val m_button_init : Jni.methodID = <abstr>
# Jni.call_void_method f m_frame_init [|Jni.Obj (Jni.string_to_java "Greetings !")|];;
- : unit = ()
# Jni.call_void_method b m_button_init [|Jni.Obj (Jni.string_to_java "Hello World")|];;
- : unit = ()
Method calls
# let m_frame_add = Jni.get_methodID class_frame
"add" "(Ljava/awt/Component;)Ljava/awt/Component;";;
val m_frame_add : Jni.methodID = <abstr>
# Jni.call_object_method f m_frame_add [| Jni.Obj b |];;
- : Jni.obj = <abstr>
# Jni.call_void_method f m_frame_pack [||];;
- : unit = ()
# Jni.call_void_method f m_frame_show [||];;
- : unit = ()
Minimal dynamic type checking
# Jni.call_object_method f m_frame_add [| Jni.Camlint 0 |];;
Exception: Jni.Exception _.
# Jni.call_object_method f m_frame_add [| Jni.Obj (Jni.string_to_java "loosy component object") |];;
Bus error
# Jni.call_object_method an_object_uncompatible_with_class_frame m_frame_pack [||];;
Bus error
6.4 Basic example
File p.idl from sections 3.2 and 5.1:
package mypack;
class Point {
int x;
int y;
[name default_point] <init> ();
[name point] <init> (int,int);
void moveto(int,int);
void rmoveto(int,int);
string toString();
void display();
double distance();
boolean eq(Point);
}
[callback] class ColoredPoint extends Point {
[name default_colored_point] <init> ();
[name colored_point] <init> (int,int,string);
[name eq_colored_point] boolean eq(ColoredPoint);
string getColor();
void setColor(string);
}
class Cloud {
[name empty_cloud] <init> ();
void addPoint(Point);
string toString();
}
6.4.2 main-point.ml
File main-point.ml from section 3.2:
open P
let display s = print_string s; flush stdout ;;
display "Creation d'un point p : ";;
let p = new default_point ();;
display "OK\n";;
display "Creation d'un point p2 = (1,1) : ";;
let p2 = new point 1 1;;
display "OK\n";;
display "Envoi p#display : ";;
p#display ();;
display "Envoi p2#display : ";;
p2#display ();;
display "Envoi p#moveto 4 3 : ";;
p#moveto 4 3;;
p#display ();;
display "Envoi p#rmoveto 2 -2 : ";;
p#rmoveto 2 ~-2;;
p#display ();;
display "Envoi p2#toString : ";;
let s = p2#toString () in print_string s; print_newline ();;
display "Envoi p2#distance : ";;
let d = p2#distance () in print_float d; print_newline ();;
display "Envoi p2#set_x 4 : ";;
p2#set_x 4;;
p2#display ();;
display "Creation d'un point colore pc = (1,3) cyan : ";;
let pc = new colored_point 1 3 "cyan";;
display "OK\n";;
display "Creation d'un point colore pc2 = (2,3) blue : ";;
let pc2 = new colored_point 1 3 "blue";;
display "OK\n";;
display "Envoi pc#display : ";;
pc#display ();;
display "Envoi pc2#display : ";;
pc2#display ();;
display "Envoi pc2#getColor : ";;
let s = pc2#getColor () in print_string s; print_newline ();;
display "Creation d'un nuage de point : ";;
let n = new empty_cloud ();;
display "OK\n";;
display "Ajout des points p2 pc1 pc2 p1 au nuage n: ";;
n#addPoint p2;;
n#addPoint (pc :> jPoint);;
n#addPoint (pc2 :> jPoint);;
n#addPoint p;;
display "OK\n";;
display "Envoi n#toString : ";;
let s = n#toString () in print_string s; print_newline ();;
class ml_colored_point x y c =
object
inherit _stub_colored_point x y c as super
method getColor () = "Caml"^(super#getColor ())
end;;
display "Creation d'un point callback cb1 = (5,6) blue ";;
let cb1 = new ml_colored_point 5 6 "blue";;
display "OK\n";;
display "Envoi cb1#getColor : ";;
let s = cb1#getColor () in print_string s; print_newline ();;
display "Envoi cb1#toString : ";;
let s = cb1#toString () in print_string s; print_newline ();;
display "Ajout du point cb au nuage n: ";;
n#addPoint (cb1 :> jPoint);;
display "OK\n";;
display "Envoi n#toString : ";;
let s = n#toString () in print_string s; print_newline ();;
File Makefile:
# $Id: ojacare.tex,v 1.21 2004/06/01 15:07:00 emmanuel Exp $
include ../Makefile.config
# Nom de l'éxécutable
EXEC = point
# Liste des fichiers IDL
IDL = p
# Liste des répertoires contenant les modules et bibliotèques Caml utilisées
MLINCDIRS =
# Liste des modules Caml
MODULES =
# Liste des bibliothèques Caml à inclure à l'édition de lien
LIBRARIES =
# Liste des bibliothèques C à inclure à l'édition de lien
CLIBS =
# Liste des classes Java à compiler
CLASS = mypack/Point mypack/Colored mypack/ColoredPoint mypack/Cloud
# Liste des classes Java ayant l'attribut callback
CBCLASS = mypack/ColoredPoint
include $(OJACAREDIR)/Makefile.include
File Makefile.config:
OCAMLC = ocamlc
OCAMLOPT = ocamlopt.opt
OCAMLMKLIB = ocamlmklib
OCAMLLEX = ocamllex
OCAMLYACC = ocamlyacc
OCAMLDEP = ocamldep
OCAMLMKTOP = ocamlmktop
OJACARE = ojacare
OJACAREDIR = $(shell $(OCAMLC) -where)/ojacare
CAMLJAVADIR = $(shell $(OCAMLC) -where)/camljava
This document was translated from LATEX by
HEVEA.