[JNI] Appeler une DLL Fortran à partir de Java
Bonjour à tous,
Ma situation est assez spéciale, je souhaiterais faire appel à des fonctions Fortran sous Windows (compilées dans une DLL) depuis un programme Java. Pour cela j’utilise la librairie Java Native Interface. Avant tout, j'essai de commencer très simple avec le fameux programme HelloWorld. Malheureusement je n’y arrive pas et j’ai besoin de votre aide. J’ai réussi dans un premier temps à linker le Java et le C++ sans problème, mais je bloque à l’étape suivante : lecture la DLL Fortran à partir du C++
J’essai d’utiliser les compilateurs GNU open source pour réaliser cela, c'est-à-dire gcc (g++) et gfortran.
Voici les étapes que j’ai réalisée jusque la :
1- Installation de Java 6.0 et Eclipse 3.4
2- Installation de gfortran (http://gcc.gnu.org/wiki/GFortran)
3- Installation de devCpp (http://sourceforge.net/projects/dev-cpp/)
4- Création du programme HelloWorld fortran (fichier helloworld.f90)
helloworld.f90
Code:
1 2 3 4
|
program helloworld
write(*,*) "Hello world!"
end program helloworld |
5- Compilation du programme avec gfortran (option –c) :
Code:
1 2
|
"C:\Program Files\gfortran\bin\gfortran.exe" -c D:\helloworld.f90 |
Remarque : J’ai également vu sur certain site l’option –fPIC qui était utilisée mais celle-ci n’a pas l’air d’être utile puisqu’elle génère le message suivant : f951.exe: warning: -fPIC ignored for target (all code is position independent)
6- Création de la DLL toujours avec gfortran (options -Xlinker -shared –o) :
Code:
1 2
|
"C:\Program Files\gfortran\bin\gfortran.exe" -shared -o D:\helloworld.dll D:\helloworld.o |
Remarque : j’ai essayé la commande avec d’autres options que j’ai pu voir :
Code:
1 2
|
"C:\Program Files\gfortran\bin\gfortran.exe" -Xlinker -shared -o D:\helloworld.dll D:\helloworld.o |
Code:
1 2
|
"C:\Program Files\gfortran\bin\gfortran.exe" -shared -mtrd -o D:\helloworld.dll D:\helloworld.o |
Code:
1 2
|
"C:\Program Files\gfortran\bin\gfortran.exe" -Xlinker --add-stdcall-alias -shared -o D:\helloworld.dll D:\helloworld.o |
Mais cela n’a pas l’air de changer quelque chose.
A la suite de cette étape, j’obtiens la DLL Fortran helloworld.dll
7- Création du fichier Java FortranExecuter.java et de la méthode native helloworld()
FortranExecuter.java
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
public class FortranExecuter {
private static native double helloworld();
static {
System.load("D:\\FortranExecuter.dll");
}
public static void main(String[] args) {
FortranExecuter.helloworld();
}
} |
8- Compilation du fichier FortranExecuter.java
Code:
1 2
|
C:\j2sdk6.0.7\jdk\bin\javac.exe D:\FortranExecuter.java |
9- Génération du fichier d’entete .h avec la commande javah.exe
Code:
1 2
|
C:\j2sdk6.0.7\jdk\bin\javah.exe -classpath D:\ -d D:\ -jni FortranExecuter |
10- Modification du fichier FortranExecuter.h généré en ajoutant la méthode cobol externe
FortranExecuter.h
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class FortranExecuter */
#ifndef _Included_FortranExecuter
#define _Included_FortranExecuter
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: FortranExecuter
* Method: helloworld
* Signature: ()D
*/
JNIEXPORT jdouble JNICALL Java_FortranExecuter_helloworld(JNIEnv *, jclass);
void helloworld_();
#ifdef __cplusplus
}
#endif
#endif |
Remarque : dans d'autres discussions, j'ai parfois vu l'utilisation des macros __declspec (dllexport) et __stdcall devant la méthode externe, j'ai fait quelques tests mais en vain. je ne sais pas trop à quoi ces directives servent.
11- Création du fichier FortranExecuter.cpp
FortranExecuter.cpp
Code:
1 2 3 4 5 6 7 8 9
|
// FortranExecuter.cpp
#include <jni.h>
#include <stdio.h>
#include "FortranExecuter.h"
JNIEXPORT jdouble JNICALL Java_FortranExecuter_helloworld(JNIEnv * env, jclass cl) {
helloworld_();
} |
12- Compilation du programme avec g++ (option –c) :
Code:
1 2
|
C:\Dev-Cpp\bin\g++.exe -I"C:\j2sdk6.0.7\jdk\include" -I"C:\j2sdk6.0.7\jdk\include\win32" -c D:\FortranExecuter.cpp -o D:\FortranExecuter.o |
13- Création de la DLL C toujours avec g++ (options -Xlinker --add-stdcall-alias -shared -o) :
Code:
1 2
|
C:\Dev-Cpp\bin\g++.exe -Xlinker --add-stdcall-alias -shared -o D:\FortranExecuter.dll D:\FortranExecuter.o |
Cette commande génère l’érreur de lien suivante me disant qu’il ne trouve pas la fonction helloworld :
Code:
1 2 3
|
D:\FortranExecuter.o(.text+0x7):FortranExecuter.cpp: undefined reference to `helloworld_'
collect2: ld returned 1 exit status |
Remarque : j’ai essayé de déplacer la DLL fortran dans les fichiers systèmes mais sans résultat. J’ai également essayé certaines options mais j’ai peur qu’il manque quelquechose dans ma démarche.
Auriez vous des conseils / idées afin de faire marcher le lien ? Je n'ai trouvé aucun tutoriel viable sur le net et j'ai également consulté certaines autres discussions sur ces pages :
http://www.developpez.net/forums/d34...fortran-c-cpp/
http://www.developpez.net/forums/d63...ant-creer-dll/
http://www.developpez.net/forums/d37...n-fortran-cpp/