www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - how to invoke D from java through JNI ? [ Linux ]

reply outersky <outersky gmail.com> writes:
hi, all
    I'm using ubuntu gutsy and jdk6 ,  and can run  D and java programs.
    Now I can call c functions from java through JNI.
    I need convert .o file to .so  for c files. But when I did so with D
files, It did not work, and output the error message as :

-------------8<---Error message----------------

/mnt/work/dev/d/java/jni3/libfunc.so: undefined symbol: _Dmodule_ref
java: symbol lookup error: /mnt/work/dev/d/java/jni3/libhello.so:
undefined symbol: hello

-------------8<---Error message----------------

I don't know how to write JNI application with D directly, so I call D
from C , and call C from java  :)

Following is my source code, and the attachment jni.zip has the same
content , and is for your convinence to test.

public class Hello{
        }catch(UnsatisfiedLinkError e){
            System.err.println( "Cannot load library:\n " +e.toString() );

    public Hello(){

    public native void SayHello(String strName);

and java generate Hello.h as

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class Hello */

#ifndef _Included_Hello
#define _Included_Hello
#ifdef __cplusplus
extern "C" {
 * Class:     Hello
 * Method:    SayHello
 * Signature: (Ljava/lang/String;)V
JNIEXPORT void JNICALL Java_Hello_SayHello
  (JNIEnv *, jobject, jstring);

#ifdef __cplusplus


#include "Hello.h"
#include <string.h>

// want to call hello written in D
extern void hello(const char* name);

JNIEXPORT void JNICALL Java_Hello_SayHello
(JNIEnv * env, jobject arg, jstring string){
  const char *str = (*env)->GetStringUTFChars(env, string, 0);

-------------8<----- func.d-------------8<------------------
  void hello(const char* name){
    printf("Hello from D: %s",name);

  Here is my build file:

echo "Compiling Hello.java ..."
javac Hello.java

echo "Generate Hello.h ..."
javah Hello

echo "Compile Hello.c , Generate Hello.o ..."
gcc -I/mnt/soft/jdk/include -I/mnt/soft/jdk/include/linux -fPIC -c Hello.c

echo "Compile func.d ..."
dmd -g -c func.d

echo "Generate shared library libhello.so.1.0"
gcc -shared -W1,-soname,libhello.so.1 -o libhello.so.1.0 Hello.o

echo "Generate shared library libfunc.so.1.0"
gcc -shared -W1,-soname,libfunc.so.1 -o libfunc.so.1.0 func.o

echo "copy libhello.so.1.0 to libhello.so"
cp libhello.so.1.0 libhello.so

echo "copy libfunc.so.1.0 to libfunc.so"
cp libfunc.so.1.0 libfunc.so

echo "Set LD_LIBRARY_PATH ..."

echo "Compile Main.java ..."
javac Main.java

echo "Run java Main ..."
java Main


  Note : My jdk is installed in /mnt/soft/jdk , you should correct this
if you want to run the build file.


Nov 07 2007
parent Frank Benoit <keinfarbton googlemail.com> writes:

I think you will not succeed with JNI.
The ultimative problem is, both Java and D have Garbage Collectors.
They both need to have control over which threads are running or not. So
this is a really hard problem.

Better solution is to make inter process communication.

I am working on a DBus binding for D. And actually i am already using it
in an application.
In the moment this enable you to call D from Java. The other direction
will follow in some time.

you can download the source with mercurial version control:
hg clone http://hg.assembla.com/dbus-d

Nov 08 2007