Ошибки в связывании кода fortran, который импортирует MAT-файл

Мне нужно импортировать MAT-файл в программу на фортране. Я выполнил пример файла, но столкнулся с некоторыми проблемами при связывании. Компиляция проходит нормально.

Минимальный код:

#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

Нужен ли мне make-файл или дополнительные аргументы в команде компиляции?

ИЗМЕНИТЬ:

Я добавил опцию -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, я все равно получаю те же ошибки.


person WYSIWYG    schedule 12.05.2015    source источник


Ответы (2)


Для файлов с расширениями нижнего регистра *.f90 или *.f препроцессор обычно деактивирован. Чтобы включить это, либо переименуйте (основной) файл, чтобы он имел заглавное расширение *.F90 или *.F, либо укажите соответствующий параметр командной строки (-cpp для gfortran, -fpp для ifort).

Предполагая, что отсутствующие подпрограммы/функции фактически объявлены в fintrf.h, это должно решить вашу проблему.

Вы должны дополнительно указать компилятору компоновать библиотеки, содержащие функции Matlab.

person Alexander Vogt    schedule 12.05.2015
comment
Вы можете указать включаемые каталоги с помощью -I/patch/to/includes и связать каталоги с -L/path/to/libs. - person Alexander Vogt; 12.05.2015
comment
При создании make-файла, где я должен указать параметр -cpp. В CFLAGS ? - person WYSIWYG; 12.05.2015
comment
Это зависит... Мне нужно увидеть Makefile. Но обычно это либо CFLAGS, либо FFLAGS. - person Alexander Vogt; 12.05.2015

Как указал Александр Фогт, компилятору требуется опция -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

Также см. этот пост о той же проблеме в C.

person WYSIWYG    schedule 12.05.2015