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