注意一点:
调用函数java里面的fortran函数名字要全部大写!!!!
本文使用的是java 的JNA实现对fortran dll的调用,所以你需要先安装JNA库。
第一次java调用fortran的dll时,总是报错 Exception in thread “main” java.lang.UnsatisfiedLinkError: Error looking up function ‘ap8ae8’: 找不到指定的程序。后来看网上(
http://blog.sina.com.cn/s/blog_4ed144110102wnqh.html
)说是问题的关键在于F77为过程名自动添加了一个尾部的下划线,所以fortran 里面定义的sub1()子程序,在java里面要改成sub1_()。我深以为然,结果改过来依然报同样的错误。网上找了很多材料,还是没有解决问题。
后来我在网上找C++调用fortran 的dll 的成功例子时,意外发现fortran里面的函数名称是小写的,但C++里面调用的函数名字是大写的。我赶紧把java里面的调用函数名称大写,结果成功了!
附上部分fortran 代码:
ap8ae8.f90
!
! FUNCTIONS/SUBROUTINES exported from ap8ae8.dll:
! ap8ae8 – subroutine
!
subroutine ap8ae8(OutputFileName,lenOfOutputFileName,
1coordType,
1L_FROMFILE_Start,L_FROMFILE_End, L_FROMFILE_Gap,
1BB0_FROMFILE_Start,BB0_FROMFILE_End,BB0_FROMFILE_Gap,xlatStart,
1xlatEnd,xlatGap,xlongStart,xlongEnd,xlongGap,yearStart,yearEnd,
1yearGap,heightStart,heightEnd,heightGap, MODEL, FLUXTYPE, E1, E2)
! Expose function apae20151108flux to users of this DLL
!
!DEC$ ATTRIBUTES DLLEXPORT::ap8ae8
! Variables
! Body of apae20151108flux
real L_FROMFILE_Start,L_FROMFILE_End, L_FROMFILE_Gap,
1BB0_FROMFILE_Start,BB0_FROMFILE_End,BB0_FROMFILE_Gap,
1xlatStart,xlatEnd,xlatGap,xlongStart,xlongEnd,xlongGap,
1yearStart,yearEnd,yearGap,heightStart,
1heightEnd,heightGap, E1, E2
integer coordType,MODEL, FLUXTYPE
CHARACTER, dimension(*), intent(in) :: OutputFileName
CHARACTER(len=lenOfOutputFileName):: FNM
INTEGER :: lenFNM
do i=1,lenOfOutputFileName
FNM(i:i)=OutputFileName(i)
end do
call ap8ae8main(OutputFileName,lenOfOutputFileName,coordType,
1L_FROMFILE_Start,L_FROMFILE_End, L_FROMFILE_Gap,
1BB0_FROMFILE_Start,BB0_FROMFILE_End,BB0_FROMFILE_Gap,xlatStart,
1xlatEnd,xlatGap,xlongStart,xlongEnd,xlongGap,yearStart,yearEnd,
1yearGap,heightStart,heightEnd,heightGap, MODEL, FLUXTYPE, E1, E2)
write(*,*)”hello!”
end subroutine
subroutine ap8ae8main(OutputFileName,lenOfOutputFileName,
1coordType,L_FROMFILE_Start,L_FROMFILE_End, L_FROMFILE_Gap,
1BB0_FROMFILE_Start,BB0_FROMFILE_End,BB0_FROMFILE_Gap,xlatStart,
1xlatEnd,xlatGap,xlongStart,xlongEnd,xlongGap,yearStart,yearEnd,
1yearGap,heightStart,heightEnd,heightGap, MODEL, FLUXTYPE, E1, E2)
real L_FROMFILE_Start,L_FROMFILE_End, L_FROMFILE_Gap,
1BB0_FROMFILE_Start,BB0_FROMFILE_End,BB0_FROMFILE_Gap,xlatStart,
1xlatEnd,xlatGap,xlongStart,xlongEnd,xlongGap,yearStart,yearEnd,
1yearGap,heightStart,heightEnd,heightGap
real L_FROMFILE, BB0_FROMFILE, E1, E2,FLUX1,YEAR,LATI,LONGI,HEIGHT
integer MODEL, FLUXTYPE,coordType
CHARACTER, dimension(*), intent(in) :: OutputFileName
CHARACTER(len=lenOfOutputFileName):: FNM
INTEGER :: lenFNM
do i=1,lenOfOutputFileName
FNM(i:i)=OutputFileName(i)
end do
IF(coordType.EQ.1) THEN
OPEN(UNIT=10,FILE=FNM, status=”replace”,access=’append’,
1FORM=’FORMATTED’)
WRITE(10,90000)
…………
注意:
!DEC$ ATTRIBUTES DLLEXPORT::ap8ae8 里面的ap8ae8名字必须与subroutine ap8ae8()名字相同
,但与.for文件的名字无关
成功调用的java代码:
(1)接口代码FLib.java
import com.sun.jna.Library;
import com.sun.jna.ptr.ByReference;
public interface FLib extends Library {
void ap8ae8(String OutputFileName,ByReference lenOfOutputFileName, ByReference coordType,ByReference L_FROMFILE_Start,ByReference L_FROMFILE_End, ByReference L_FROMFILE_Gap,ByReference BB0_FROMFILE_Start,ByReference BB0_FROMFILE_End,ByReference BB0_FROMFILE_Gap,ByReference xlatStart,ByReference xlatEnd,ByReference xlatGap,ByReference xlongStart,ByReference xlongEnd,ByReference xlongGap,ByReference yearStart,ByReference yearEnd,ByReference yearGap,ByReference heightStart,ByReference heightEnd,ByReference heightGap,ByReference MODEL, ByReference FLUXTYPE, ByReference E1,ByReference E2);
}
(2)调用代码Main.java
import com.sun.jna.Native;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.DoubleByReference;
import com.sun.jna.ptr.FloatByReference;
public class Main {
public static void main(String[] args) {
// Loading dynamically the library
FLib lib2=(FLib) Native.loadLibrary(“D:\\Project\\eclipse\\apaetest\\bin\\ap8ae8.dll”, FLib.class);
String OutputFileName = “D:\\TEST.txt”;
IntByReference lenOfOutputFileName=new IntByReference(OutputFileName.length());
IntByReference MODEL=new IntByReference(1);
IntByReference coordType=new IntByReference(1);
IntByReference FLUXTYPE=new IntByReference(1);
FloatByReference L_FROMFILE_Start=new FloatByReference(1);
FloatByReference L_FROMFILE_End=new FloatByReference(2);
FloatByReference L_FROMFILE_Gap=new FloatByReference(1);
FloatByReference BB0_FROMFILE_Start=new FloatByReference(1);
FloatByReference BB0_FROMFILE_End=new FloatByReference(2);
FloatByReference BB0_FROMFILE_Gap=new FloatByReference(1);
FloatByReference xlatStart=new FloatByReference(1);
FloatByReference xlatEnd=new FloatByReference(2);
FloatByReference xlatGap=new FloatByReference(1);
FloatByReference xlongStart=new FloatByReference(1);
FloatByReference xlongEnd=new FloatByReference(2);
FloatByReference xlongGap=new FloatByReference(1);
FloatByReference yearStart=new FloatByReference(1);
FloatByReference yearEnd=new FloatByReference(2);
FloatByReference yearGap=new FloatByReference(1);
FloatByReference heightStart=new FloatByReference(1);
FloatByReference heightEnd=new FloatByReference(2);
FloatByReference heightGap=new FloatByReference(1);
FloatByReference E1=new FloatByReference(1);
FloatByReference E2=new FloatByReference(1);
lib2.ap8ae8(OutputFileName,lenOfOutputFileName,coordType,
L_FROMFILE_Start,L_FROMFILE_End, L_FROMFILE_Gap,
BB0_FROMFILE_Start,BB0_FROMFILE_End,BB0_FROMFILE_Gap,xlatStart,
xlatEnd,xlatGap,xlongStart,xlongEnd,xlongGap,yearStart,yearEnd,
yearGap,heightStart,heightEnd,heightGap, MODEL, FLUXTYPE, E1, E2);
}
}
成功调用dll里面的ap8ae8函数时将会看到输出“hello!”
另外:关于!DEC$,这篇文章里面提到
https://blog.csdn.net/fengyhack/article/details/8594727
以上!DEC$打头的两行,如第一个,其另一形式如下
!MS$IF .NOT. DEFINED(LINKDIRECT)
!MS$ATTRIBUTES DLLEXPORT::FACT
!MS$ENDIF
可分别替换之,而余下代码都是一样的。