I have to import a MAT-file in a fortran program. I followed the example file but I am facing some problems while linking. The compilation happens fine.
Minimal code:
#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
I am using gfortran 4.8.3 for compiling+linking using the default command:
gfortran main.f90 dmotifs.o param.o ssa.o -o main
This code compiles fine (without linking) when I do not include: #include "finitrf.h", otherwise the compiler says
Warning: main.f90:1: Illegal preprocessor directive
I tried renaming finitrf.h to finitrf.f90 but it did not make any difference. Nonetheless during linking I am getting these errors:
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
Do I need a makefile or add additional arguments in the compile command?
EDIT:
I added the -cpp option and that eliminates the problem of Illegal preprocessor directive
Now when I am compiling with paths to matlab external components (where finitf.h) is, I am still getting the same error.
gfortran main.f90 dmotifs.o param.o ssa.o -I/usr/local/matlab2008a/extern/include -L/usr/local/matlab2008a/extern/lib -cpp -o main
If I provide library path to /usr/local/matlab2008a/bin/glnxa64 that contains other matlab libraries including libmat.so, I still get the same errors.
For lower case file extensions *.f90 or *.f the pre-processor is typically deactivated. To enable that, either rename the (main) file to have a capital extension *.F90 or *.F, or provide the corresponding command-line option (-cpp for gfortran, -fpp for ifort).
Assuming the missing subroutines/functions are actually declared in fintrf.h, this should solve your problem.
You should additionally tell the compiler to link against the libraries containing the Matlab functions.
As pointed out by Alexander Vogt, the compiler requires -cpp option for the pre-processor to recognize the header file and not to treat it as illegal.
Linking requires finitrf.h which is usually located in the <matlabroot>/extern/include and the essential libraries are present in <matlabroot>/bin/<arch>/.
But just specifying this does not work and specification of the exact matlab library seems essential; these are libmat.so and libmx.so.
These libraries are in turn dependent on other libraries so another flag is required to set the rpath.
Finally it works with following command:
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/
or in general
gfortran program.f90 -I<matlabroot>/extern/include -L<matlabroot>/bin/<arch> -cpp -lmat -lmx -Wl, -rpath <matlabroot>/bin/<arch> -o program.out
Also see this post that is about the same problem in C.
来源:https://stackoverflow.com/questions/30185571/errors-in-linking-fortran-code-that-imports-a-mat-file