Fortran& Matlab链接 - 未定义的符号

时间:2014-01-02 18:34:35

标签: compiler-errors linker fortran mex gfortran

我继承了用fortran 90编写的这个mex代码,我无法正确构建。所有目标文件编译得很好,但链接失败。 幸运的是,我有几个线索继续找出问题。

链接器的唯一抱怨是

Undefined symbols for architecture x86_64:
  "_mxgetstring_", referenced from:
      _mexfunction_ in qgstep_mex.o
ld: symbol(s) not found for architecture x86_64

现在只在qgstep_mex.f90

中的一个地方调用mxGetString
status = mxGetString(prhs(3), prmfname, STRLEN)

所以,如果我将其更改为

status = 0

和硬编码prmfname,包构建得很好。但我当然不想硬编码。

然而,我设法构建另一个使用mxGetString()的程序,即Matlab提供的示例文件revord.f

这两个程序都是由mex

生成的相同命令链接的
gcc -O -Wl,-twolevel_namespace -undefined error -arch x86_64 -Wl,-syslibroot,/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk/ -mmacosx-version-min=10.5 -bundle -Wl,-exported_symbols_list,/Applications/MATLAB_R2012a.app/extern/lib/maci64/fexport.map  -o  "revord.mexmaci64"  revord.o  -L/Applications/MATLAB_R2012a.app/bin/maci64 -lmx -lmex -lmat -L/opt/local/lib/gcc47/gcc/x86_64-apple-darwin12/4.7.3/../../.. -lgfortran -L/opt/local/lib/gcc47/gcc/x86_64-apple-darwin12/4.7.3 -lgfortranbegin

除了revord.Fqgstep_mex.f90替换,输出名称类似。

revord.F

中有一个包含声明
#include "fintrf.h"

在编译期间由标志

指向
-I/Applications/MATLAB_R2012a.app/extern/include

但是,如果我尝试将其放在qgstep_mex.f90中,则链接器只会抱怨

Warning: qgstep_mex.f90:1: Illegal preprocessor directive.

那么,有没有人知道如何使这个工作?

更新(回应M.S.B.的回答)

将扩展名的大小写更改为.F90无效,但-cpp标志似乎已成功。但是,现在它给出了一个错误(在编译期间,而不是链接)我不太明白(我对Fortran不是很好)

$ gfortran-mp-4.7 -c -I/Applications/MATLAB_R2012a.app/extern/include -I/Applications/MATLAB_R2012a.app/simulink/include -fexceptions -m64 -fbackslash -DMX_COMPAT_32 -O -cpp "qgstep_mex.f90"
qgstep_mex.f90:102.11:

  status = mxGetString700(prhs(3), prmfname, STRLEN)
           1
Error: Function 'mxgetstring700' at (1) has no IMPLICIT type

包含文件中的相关行似乎是

#if defined(MX_COMPAT_32)
.
.
.
#define mxGetString mxGetString700

更新以响应M.S.B.的更新

啊哈。看来我毕竟不应该包括fintrf.h。项目目录中有另一个文件mexf90.f90,其中包含

module mexf90_mod
  interface
     function mxGetString(p, string, STRLEN)
       integer(8) :: mxGetString
       integer(8) :: p
       character*(*) :: string
       integer(4) :: STRLEN
     end function mxGetString

     function mxGetPr(pm)
       integer(8), pointer :: mxGetPr
       integer(8) :: pm
     end function mxGetPr
.
.

奇怪的是mxGetPr在qgstep_mex.f90中被调用,在mxGetString之前,但是调用mxGetString失败,错误消息如上所述。这是我使用的链接命令(为清晰起见插入了换行符)

gfortran-mp-4.7 -O -Wl,-twolevel_namespace -undefined error -arch x86_64
-Wl,-syslibroot,/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk/
-mmacosx-version-min=10.5 -bundle -Wl,-exported_symbols_list,/Applications/MATLAB_R2012a.app/extern/lib/maci64/fexport.map
-o "QG_step_f.mexmaci64" utils.o parameters.o helmholtz.o calc.o qgflux.o qgstep.o mexf90.o qgstep_mex.o
-L/Applications/MATLAB_R2012a.app/bin/maci64 -lmx -lmex -lmat -L/opt/local/lib/gcc47/gcc/x86_64-apple-darwin12/4.7.3/../../..
-lgfortran -L/opt/local/lib/gcc47/gcc/x86_64-apple-darwin12/4.7.3 -lgfortranbegin

可以看出,目标文件似乎也是正确的顺序。

更新

该软件包在Linux系统上构建得很好。因此我想编译器之间必定存在一些区别。这是linux系统上使用的链接代码:

gfortran -O  -pthread -shared -Wl,--version-script,/ufs/local/matlab-2012a/extern/lib/glnxa64/fexport.map -Wl,--no-undefined
-o  "QG_step_f.mexa64"  utils.o parameters.o helmholtz.o calc.o qgflux.o qgstep.o mexf90.o qgstep_mex.o
-Wl,-rpath-link,/ufs/local/matlab-2012a/bin/glnxa64 -L/ufs/local/matlab-2012a/bin/glnxa64 -lmx -lmex -lmat -lm

2 个答案:

答案 0 :(得分:1)

尝试将文件名qgstep_mex.f90更改为qgstep_mex.F90。这将导致gfortran运行C预处理器。还有一个编译器选项可以解决这个问题。

编辑以回应问题更新: 编译器希望键入函数mxGetString7001。有几种方法可以做到这一点。理想的方法是在模块中包含函数的源代码。然后,当调用者use该模块时,函数的返回类型及其参数的类型对于编译器是已知的。也许这存在,您需要在使用此函数的文件之前将源代码文件添加到您的编译语句中。如果没有,您可以编写提供此信息的interface块。或者您可以声明该函数并使用external语句,但这实际上是一种解决方法,使用FORTRAN 77方法。

答案 1 :(得分:0)

fortran中的include语句没有#

include "fintrf.h"

建造时,为什么不使用gfortran而不是gcc。保存编译器必须弄清楚你正在编译的内容。