caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* Calling Java then C from a Ocaml toplevel
@ 2000-01-13 14:33 Emmanuel DORLET
  2000-01-13 17:49 ` Xavier Leroy
  0 siblings, 1 reply; 2+ messages in thread
From: Emmanuel DORLET @ 2000-01-13 14:33 UTC (permalink / raw)
  To: Liste-Caml

Hello,

Does someone ever try to call a Java program from Ocaml toplevel and
exchange
data with it?
If yes, is it possible if Java call C (then other foreign langage like say
... Fortran!)?
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 ?





^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: Calling Java then C from a Ocaml toplevel
  2000-01-13 14:33 Calling Java then C from a Ocaml toplevel Emmanuel DORLET
@ 2000-01-13 17:49 ` Xavier Leroy
  0 siblings, 0 replies; 2+ messages in thread
From: Xavier Leroy @ 2000-01-13 17:49 UTC (permalink / raw)
  To: emmanuel.dorlet, Liste-Caml

> 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




^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2000-01-14  7:43 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2000-01-13 14:33 Calling Java then C from a Ocaml toplevel Emmanuel DORLET
2000-01-13 17:49 ` Xavier Leroy

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).