On 4/12/2011 7:25 PM, Jerry DeLisle wrote:
On 04/12/2011 07:38 AM, Hans Horn wrote:
Folks,

has anybody got any experience interfacing (g)fortran routines with
Java via JNI?

I'm on 64bit Windows7 using cygwin
x86_64-w64-mingw32-gcc and x86_64-w64-mingw32-gfortran, both v4.5.2

Java: jdk-6u24-windows-x64

Even though I can statically link the JNI code successfully (using
gfortran as
linker), calling any native method from Java crashes the JVM - even
when no
fortran code is called at all.

What do you mean by native method? Are you trying to call Fortran
procedures from Java?

In what way does it crash? Can you get a back trace from a debugger?

Jerry

PS I have no experience with this, just asking some questions to glean
additional information. Fortran calling conventions are no exactly the
same as C.

Ok,

> What do you mean by native method? Are you trying to call Fortran
> procedures from Java?
Nope, via a C wrapper.

I condensed things to the simplest possible testcase that still does not function. In the process I figured that I needed to link with '-shared'. Without that I get said crash of the JVM in both cases, with or without calling fortran.



here's my fortran routine:
------------------------------------------------
      subroutine f77sub(string)
      character*(*) string

      write(*,*) 'string is ',string
      call fflush(6)

      end


here's the JNI C wrapper that calls the fortran routine:
------------------------------------------------
#include "JNItest.h"

#ifdef F77SUB
  void f77sub(char*, int);
#endif

JNIEXPORT void JNICALL Java_JNItest_java2C2f77
(JNIEnv* env, jclass obj) {
#ifdef F77SUB
  printf("calling fortran\n"); fflush(stdout);
  f77sub("here is fortran", 15);
  printf("back from fortran\n"); fflush(stdout);
#else
  printf("not calling fortran at all\n"); fflush(stdout);
#endif
}


here's my Java class calling the JNI C wrapper:
------------------------------------------------
class JNItest {
  private native void java2C2f77 ();
  static {
    System.loadLibrary("jnitest");
  }
  public static void main (String[] args) {
    new JNItest().java2C2f77();
  }
}


here's the makefile used to compile the jnitest.dll:
------------------------------------------------
gcc_opt = -O3 -std=c99 -DCYGWIN -Wl,--kill-at \
-fno-omit-frame-pointer -I${JAVA_HOME}/include/win32 \ -I${JAVA_HOME}/include -Wall -D_JNI_IMPLEMENTATION_
gcc = gcc
gfc = gfortran
gfc_opt = -O3 -fno-underscoring -fno-f2c -W -Wunused \
-Wuninitialized -fno-omit-frame-pointer
ld_opt = -luuid -lole32 -fno-omit-frame-pointer -shared
ifeq ($(PROCESSOR_ARCHITEW6432), AMD64) #use mingw 64bit cross compilers
  gcc_opt += -m64
  gcc = x86_64-w64-mingw32-gcc
  gfc = x86_64-w64-mingw32-gfortran
  gfc_opt += -m64
  ld_opt += -m64
endif

########################################################################

allnof: jnitest_h jnitestnof;

jnitest_h: JNItest.class; javah -classpath ./ JNItest

jnitestnof: JNItest.c JNItest.h; \
${gcc} ${gcc_opt} JNItest.c ${ld_opt} -o jnitest.dll

########################################################################

# attempt to call fortran from JNI code; must link with gfortran else
# we're mssing fortran runtime libs, eg. _gfortran_st_write

allf: f77o jnitest_h jnitestf;

f77o: f77sub.o; ${gfc} ${gfc_opt} -c f77sub.f -o f77sub.o

jnitestf: JNItest.c JNItest.h; \
${gcc} -DF77SUB ${gcc_opt} -c JNItest.c -o JNItest.o; \
${gfc} ${ld_opt} JNItest.o f77sub.o -o jnitest.dll



--------------------------------------------------------------------------
the dll built w/o calling fortran (-DF77SUB not set; make jnitestnof) prints (as it should):
"not calling fortran at all"

---------------------------------------------------------------------------
the dll built with calling fortran (-DF77SUB set; make jnitestf, gfortran as linker) is expected to print:
calling fortran
here is fortran
back from fortran

however, it produces an unsatisfied link error such as:

java.lang.UnsatisfiedLinkError: D:\native\jnitest.dll: %1 is not a valid Win32 application
        at java.lang.ClassLoader$NativeLibrary.load(Native Method)
        at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1803)
        at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1728)
        at java.lang.Runtime.loadLibrary0(Runtime.java:823)
        at java.lang.System.loadLibrary(System.java:1028)
        at JNItest.<clinit>(JNItest.java:4)

Note that the path to the gfortran runtime is included in the Windows PATH variable:
PATH=D:\native;C:\CygWin\usr\i686-w64-mingw32\sys-root\mingw\bin;...


Thx.,
H.


--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

Reply via email to