caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Xavier Leroy <xleroy@pauillac.inria.fr>
To: emmanuel.dorlet@cea.fr, Liste-Caml <caml-list@pauillac.inria.fr>
Subject: Re: Calling Java then C from a Ocaml toplevel
Date: Thu, 13 Jan 2000 18:49:34 +0100	[thread overview]
Message-ID: <20000113184934.58381@pauillac.inria.fr> (raw)
In-Reply-To: <NDBBIOBOKNJIIGDGBOPLCEMJCBAA.emmanuel.dorlet@soleil.serma.cea.fr>; from Emmanuel DORLET on Thu, Jan 13, 2000 at 03:33:59PM +0100

> 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




      reply	other threads:[~2000-01-14  7:43 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2000-01-13 14:33 Emmanuel DORLET
2000-01-13 17:49 ` Xavier Leroy [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20000113184934.58381@pauillac.inria.fr \
    --to=xleroy@pauillac.inria.fr \
    --cc=caml-list@pauillac.inria.fr \
    --cc=emmanuel.dorlet@cea.fr \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).