> Does someone ever try to call a Java program from Ocaml toplevel and
> exchange data with it?
It can be done, using the Java Native Interface (JNI). See the files
below for a trivial, but working, example. Here is a demo:
estephe:~/essais/ocaml/Caml2Java$ ./ocamljavatop
Objective Caml version 2.99 (99/12/08)
# Javastub.init();;
- : unit = ()
# Javastub.call_Javacode_test 100;;
Javacode.test(100) called <-- printed by Java
Javacode.test returns 101 <-- printed by Java
- : int = 101 <-- 101 computed by Java
# Javastub.fini();;
- : unit = ()
# #quit;;
(Note: you may have to fight with the Unix dynamic loader quite a lot
to get this running, since the JDK loads plenty of libraries
dynamically, sometimes with hard-wired paths, but it can be made to
run. This is a JDK problem, not a Caml problem, thank you for not
asking me how to solve it :-))
I believe a much more versatile interface can be developed by stubbing
in Caml the 100+ functions provided by the JNI, thus allowing the user
to call any Java method without writing new C stub code. I haven't
tried, but this could be a nice summer internship for a student with
hacking tendencies.
> If yes, is it possible if Java call C (then other foreign langage
> like say ... Fortran!)?
Assuming that you know how to call C or Fortran from Java, I'm tempted
to say yes.
> Is there any difficult point that must be known, for example to deal
> with the data exchanges in respect with the garbage collector of
> both Caml and Java ?
The JNI provides global root registration facilities, so in principle
those could be used along with Caml finalized objects to coordinate
the two GCs. Again, I don't know how feasible this is in practice.
Hope this helps,
- Xavier Leroy
------------------------------ stubs.c -----------------------------------
#include <stdio.h>
#include <stddef.h>
#include <jni.h>
#include <caml/mlvalues.h>
#include <caml/fail.h>
static JavaVM *jvm; /* denotes a Java VM */
static JNIEnv *env; /* pointer to native method interface */
value java_init(value unit)
{
JDK1_1InitArgs vm_args; /* JDK 1.1 VM initialization arguments */
vm_args.version = 0x00010001; /* New in 1.1.2: VM version */
/* Get the default initialization arguments and set the class
* path */
JNI_GetDefaultJavaVMInitArgs(&vm_args);
vm_args.classpath = "/usr/local/jdk1.2.2/jre/lib/rt.jar:.";
/* load and initialize a Java VM, return a JNI interface
* pointer in env */
if (JNI_CreateJavaVM(&jvm, (void **) &env, &vm_args) != 0) {
failwith("JNI_CreateJavaVM failed");
}
return Val_unit;
}
value java_fini(value unit)
{
/* We are done. */
(*jvm)->DestroyJavaVM(jvm);
return Val_unit;
}
value java_call_Javacode_test(value caml_arg)
{
jclass cls;
jmethodID mid;
int arg, res;
/* invoke the Javacode.test method using the JNI */
cls = (*env)->FindClass(env, "Javacode");
if (cls == NULL) {
failwith("FindClass failed");
}
mid = (*env)->GetStaticMethodID(env, cls, "test", "(I)I");
if (mid == NULL) {
failwith("GetStaticMethodID");
}
arg = Int_val(caml_arg);
res = (*env)->CallStaticIntMethod(env, cls, mid, arg);
return Val_int(res);
}
--------------------------- Javacode.java --------------------------------
class Javacode {
static int test(int n)
{
System.out.println("Javacode.test(" + n + ") called");
int res = n + 1;
System.out.println("Javacode.test returns " + res);
return res;
}
}
--------------------------- javastub.ml -----------------------------------
external init : unit -> unit = "java_init"
external fini : unit -> unit = "java_fini"
external call_Javacode_test : int -> int = "java_call_Javacode_test"
---------------------------- Makefile -------------------------------------
CC=gcc
CFLAGS=-I/usr/local/jdk1.2.2/include -I/usr/local/jdk1.2.2/include/linux -g -Wall -I/usr/local/lib/ocaml
LFLAGS=-cclib -ljvm -cclib -lhpi
all: ocamljavatop Javacode.class
ocamljavatop: stubs.o javastub.cmo
ocamlmktop -custom -o ocamljavatop javastub.cmo stubs.o $(LFLAGS)
stubs.o: stubs.c
$(CC) -c $(CFLAGS) stubs.c
Javacode.class: Javacode.java
javac Javacode.java
javastub.cmo: javastub.ml
ocamlc -c javastub.ml
This archive was generated by hypermail 2b29 : Fri Jan 14 2000 - 08:45:53 MET