链接导入 MAT 文件的 Fortran 代码时出错
Errors in linking fortran code that imports a MAT-file
我必须在 Fortran 程序中导入 MAT 文件。我遵循了 example file 但我在链接时遇到了一些问题。编译进行得很好。
最小代码:
#include "fintrf.h"
PROGRAM main
USE ssa
USE dmotifs
USE param
IMPLICIT NONE
! MAT-FILE Declarations !
INTEGER matOpen, matGetDir
INTEGER matGetVariableInfo
INTEGER mp, dir, adir(100), pa
INTEGER mxGetM, mxGetN, matClose
INTEGER ndir, i, clstat
CHARACTER*32 names(100)
!===========================!
if(all(fnames(:)%fn .NE. argfun)) then
write(*,*) "No such motif: ",argfun
write(*,*) "Input format-> main <motifname>"
stop
else
fin=fchton(argfun)
y0=nM2m*analys(p,argfun)
! ==> OPEN MAT-file <== !
mp=matOpen('./PRMS_lxr_29Apr15.mat','r')
if (mp .eq. 0) then
write(6,*) "Can't open MAT-file"
stop
end if
dir = matgetdir(mp, ndir)
if (dir .eq. 0) then
write(6,*) "Can't read MAT-file-directory."
stop
endif
call mxCopyPtrToPtrArray(dir, adir, ndir)
do 20 i=1,ndir
call mxCopyPtrToCharacter(adir(i), names(i), 32)
20 continue
write(6,*) 'Directory of Mat-file:'
do 30 i=1,ndir
write(6,*) names(i)
30 continue
write(6,*) 'Getting Header info from first array.'
pa = matGetVariableInfo(mp, names(1))
write(6,*) 'Retrieved ', names(1)
write(6,*) ' With size ', mxGetM(pa), '-by-', mxGetN(pa)
call mxDestroyArray(pa)
clstat=matClose(mp)
end if
END PROGRAM main
我正在使用 gfortran 4.8.3 使用默认命令进行编译+链接:
gfortran main.f90 dmotifs.o param.o ssa.o -o main
当我不包含 #include "finitrf.h"
时,这段代码编译正常(没有链接),否则编译器会说
Warning: main.f90:1: Illegal preprocessor directive
我尝试将 finitrf.h
重命名为 finitrf.f90
,但没有任何区别。尽管如此,在链接过程中我还是收到了这些错误:
main.f90:(.text+0x3ea): undefined reference to `matopen_'
main.f90:(.text+0x487): undefined reference to `matgetdir_'
main.f90:(.text+0x52b): undefined reference to `mxcopyptrtoptrarray_'
main.f90:(.text+0x583): undefined reference to `mxcopyptrtocharacter_'
main.f90:(.text+0x71b): undefined reference to `matgetvariableinfo_'
main.f90:(.text+0x804): undefined reference to `mxgetm_'
main.f90:(.text+0x855): undefined reference to `mxgetn_'
main.f90:(.text+0x89c): undefined reference to `mxdestroyarray_'
main.f90:(.text+0x8b0): undefined reference to `matclose_'
collect2: error: ld returned 1 exit status
我是否需要生成文件或在编译命令中添加额外的参数?
编辑:
我添加了 -cpp
选项并消除了 Illegal preprocessor directive
的问题
现在,当我使用 matlab 外部组件(其中 finitf.h)的路径进行编译时,我仍然遇到相同的错误。
gfortran main.f90 dmotifs.o param.o ssa.o -I/usr/local/matlab2008a/extern/include -L/usr/local/matlab2008a/extern/lib -cpp -o main
如果我提供 /usr/local/matlab2008a/bin/glnxa64
的库路径,其中包含其他 matlab 库,包括 libmat.so
,我仍然会遇到相同的错误。
对于小写文件扩展名 *.f90
或 *.f
,预处理器通常被停用。要启用该功能,请将(主)文件重命名为大写扩展名 *.F90
或 *.F
,或者提供相应的命令行选项(-cpp
for gfortran
,-fpp
对应 ifort
)。
假设缺失的 subroutines/functions 实际上是在 fintrf.h
中声明的,这应该可以解决您的问题。
您还应该告诉编译器 link 针对包含 Matlab 函数的库。
正如 Alexander Vogt 所指出的,编译器需要 -cpp
预处理器选项来识别头文件而不将其视为非法。
链接需要 finitrf.h
,它通常位于 <matlabroot>/extern/include
中,基本库存在于 <matlabroot>/bin/<arch>/
中。
但是仅仅指定它是行不通的,确切的 matlab 库的规范似乎是必不可少的;它们是 libmat.so
和 libmx.so
。
这些库又依赖于其他库,因此需要另一个标志来设置 rpath
。
终于可以使用以下命令了:
gfortran main.f90 dmotifs.o param.o ssa.o -I/usr/local/matlab2008a/extern/include -L/usr/local/matlab2008a/bin/glnxa64 -cpp -o main -lmat -lmx -Wl,-rpath /usr/local/matlab2008a/bin/glnxa64/
或一般
gfortran program.f90 -I<matlabroot>/extern/include -L<matlabroot>/bin/<arch> -cpp -lmat -lmx -Wl, -rpath <matlabroot>/bin/<arch> -o program.out
另请参阅 this post,这与 C
中的问题大致相同。
我必须在 Fortran 程序中导入 MAT 文件。我遵循了 example file 但我在链接时遇到了一些问题。编译进行得很好。
最小代码:
#include "fintrf.h"
PROGRAM main
USE ssa
USE dmotifs
USE param
IMPLICIT NONE
! MAT-FILE Declarations !
INTEGER matOpen, matGetDir
INTEGER matGetVariableInfo
INTEGER mp, dir, adir(100), pa
INTEGER mxGetM, mxGetN, matClose
INTEGER ndir, i, clstat
CHARACTER*32 names(100)
!===========================!
if(all(fnames(:)%fn .NE. argfun)) then
write(*,*) "No such motif: ",argfun
write(*,*) "Input format-> main <motifname>"
stop
else
fin=fchton(argfun)
y0=nM2m*analys(p,argfun)
! ==> OPEN MAT-file <== !
mp=matOpen('./PRMS_lxr_29Apr15.mat','r')
if (mp .eq. 0) then
write(6,*) "Can't open MAT-file"
stop
end if
dir = matgetdir(mp, ndir)
if (dir .eq. 0) then
write(6,*) "Can't read MAT-file-directory."
stop
endif
call mxCopyPtrToPtrArray(dir, adir, ndir)
do 20 i=1,ndir
call mxCopyPtrToCharacter(adir(i), names(i), 32)
20 continue
write(6,*) 'Directory of Mat-file:'
do 30 i=1,ndir
write(6,*) names(i)
30 continue
write(6,*) 'Getting Header info from first array.'
pa = matGetVariableInfo(mp, names(1))
write(6,*) 'Retrieved ', names(1)
write(6,*) ' With size ', mxGetM(pa), '-by-', mxGetN(pa)
call mxDestroyArray(pa)
clstat=matClose(mp)
end if
END PROGRAM main
我正在使用 gfortran 4.8.3 使用默认命令进行编译+链接:
gfortran main.f90 dmotifs.o param.o ssa.o -o main
当我不包含 #include "finitrf.h"
时,这段代码编译正常(没有链接),否则编译器会说
Warning: main.f90:1: Illegal preprocessor directive
我尝试将 finitrf.h
重命名为 finitrf.f90
,但没有任何区别。尽管如此,在链接过程中我还是收到了这些错误:
main.f90:(.text+0x3ea): undefined reference to `matopen_'
main.f90:(.text+0x487): undefined reference to `matgetdir_'
main.f90:(.text+0x52b): undefined reference to `mxcopyptrtoptrarray_'
main.f90:(.text+0x583): undefined reference to `mxcopyptrtocharacter_'
main.f90:(.text+0x71b): undefined reference to `matgetvariableinfo_'
main.f90:(.text+0x804): undefined reference to `mxgetm_'
main.f90:(.text+0x855): undefined reference to `mxgetn_'
main.f90:(.text+0x89c): undefined reference to `mxdestroyarray_'
main.f90:(.text+0x8b0): undefined reference to `matclose_'
collect2: error: ld returned 1 exit status
我是否需要生成文件或在编译命令中添加额外的参数?
编辑:
我添加了 -cpp
选项并消除了 Illegal preprocessor directive
现在,当我使用 matlab 外部组件(其中 finitf.h)的路径进行编译时,我仍然遇到相同的错误。
gfortran main.f90 dmotifs.o param.o ssa.o -I/usr/local/matlab2008a/extern/include -L/usr/local/matlab2008a/extern/lib -cpp -o main
如果我提供 /usr/local/matlab2008a/bin/glnxa64
的库路径,其中包含其他 matlab 库,包括 libmat.so
,我仍然会遇到相同的错误。
对于小写文件扩展名 *.f90
或 *.f
,预处理器通常被停用。要启用该功能,请将(主)文件重命名为大写扩展名 *.F90
或 *.F
,或者提供相应的命令行选项(-cpp
for gfortran
,-fpp
对应 ifort
)。
假设缺失的 subroutines/functions 实际上是在 fintrf.h
中声明的,这应该可以解决您的问题。
您还应该告诉编译器 link 针对包含 Matlab 函数的库。
正如 Alexander Vogt 所指出的,编译器需要 -cpp
预处理器选项来识别头文件而不将其视为非法。
链接需要 finitrf.h
,它通常位于 <matlabroot>/extern/include
中,基本库存在于 <matlabroot>/bin/<arch>/
中。
但是仅仅指定它是行不通的,确切的 matlab 库的规范似乎是必不可少的;它们是 libmat.so
和 libmx.so
。
这些库又依赖于其他库,因此需要另一个标志来设置 rpath
。
终于可以使用以下命令了:
gfortran main.f90 dmotifs.o param.o ssa.o -I/usr/local/matlab2008a/extern/include -L/usr/local/matlab2008a/bin/glnxa64 -cpp -o main -lmat -lmx -Wl,-rpath /usr/local/matlab2008a/bin/glnxa64/
或一般
gfortran program.f90 -I<matlabroot>/extern/include -L<matlabroot>/bin/<arch> -cpp -lmat -lmx -Wl, -rpath <matlabroot>/bin/<arch> -o program.out
另请参阅 this post,这与 C
中的问题大致相同。