如何在Matlab';s MEX编译

如何在Matlab';s MEX编译,matlab,openmp,linker-errors,mex,Matlab,Openmp,Linker Errors,Mex,我写了一个如下形式的程序: #include "stuff_I_need.h" int main(){ construct_array(); // uses OpenMP pragma's print_array(); return(0); } 使用以下命令正确编译、链接和运行: `gcc44 -I/home/matteson/sundials/include/ main.c -lm -L/home/matteson/sundials/lib -lsundials_cvode -ls

我写了一个如下形式的程序:

#include "stuff_I_need.h"

int main(){

construct_array(); // uses OpenMP pragma's
print_array();

return(0);


}
使用以下命令正确编译、链接和运行:

`gcc44 -I/home/matteson/sundials/include/ main.c -lm -L/home/matteson/sundials/lib -lsundials_cvode -lsundials_nvecserial -fopenmp -o /home/matteson/MPI_test/CVODE_test/main_test`
“gcc44”只是gcc版本4.4,之所以这样命名是因为它是在维护多个gcc版本的集群上编译的。在阵列构建过程中,库Sundals_cvode和Sundals_InvecSerial用于求解几个微分方程

现在,当我想转到Matlab并尝试编译表单的mex文件时:

#include "stuff_I_need.h"

void mexFunction(int nlhs,mxArray* plhs[], int nrhs, const mxArray* prhs[]){

construct_array(); // uses OpenMP pragma's
print_array();

}
并尝试在Matlab中使用以下命令进行编译:

>> mex -v CC="gcc44" CFLAGS="\$CFLAGS -I/home/matteson/sundials/include/ -fopenmp" LDFLAGS="\$LDFLAGS -fopenmp -L/home/matteson/sundials/lib -lsundials_cvode -lsundials_nvecserial" mex_cvode.c
我收到以下消息,最终导致链接错误:

    -> mexopts.sh sourced from directory (DIR = $HOME/.matlab/$REL_VERSION)
   FILE = /home/matteson/.matlab/R2010b/mexopts.sh
----------------------------------------------------------------
->    MATLAB                = /misc/linux/64/opt/pkg/matlab/R2010b
->    CC                    = gcc44
->    CC flags:
         CFLAGS             = -ansi -D_GNU_SOURCE  -fexceptions -fPIC -fno-omit-frame-pointer -pthread -I/home/matteson/sundials/include/ -L/home/matteson/sundials/lib -lsundials_cvode -L/home/matteson/sundials/lib -lsundials_nvecserial
         CDEBUGFLAGS        = -g
         COPTIMFLAGS        = -O -DNDEBUG
         CLIBS              = -Wl,-rpath-link,/misc/linux/64/opt/pkg/matlab/R2010b/bin/glnxa64 -L/misc/linux/64/opt/pkg/matlab/R2010b/bin/glnxa64 -lmx -lmex -lmat -lm -lstdc++
         arguments          =  -DMX_COMPAT_32
->    CXX                   = g++
->    CXX flags:
         CXXFLAGS           = -ansi -D_GNU_SOURCE -fPIC -fno-omit-frame-pointer -pthread
         CXXDEBUGFLAGS      = -g
         CXXOPTIMFLAGS      = -O -DNDEBUG
         CXXLIBS            = -Wl,-rpath-link,/misc/linux/64/opt/pkg/matlab/R2010b/bin/glnxa64 -L/misc/linux/64/opt/pkg/matlab/R2010b/bin/glnxa64 -lmx -lmex -lmat -lm
         arguments          =  -DMX_COMPAT_32
->    FC                    = g95
->    FC flags:
         FFLAGS             = -fexceptions -fPIC -fno-omit-frame-pointer
         FDEBUGFLAGS        = -g
         FOPTIMFLAGS        = -O
         FLIBS              = -Wl,-rpath-link,/misc/linux/64/opt/pkg/matlab/R2010b/bin/glnxa64 -L/misc/linux/64/opt/pkg/matlab/R2010b/bin/glnxa64 -lmx -lmex -lmat -lm
         arguments          =  -DMX_COMPAT_32
->    LD                    = gcc44
->    Link flags:
         LDFLAGS            = -pthread -shared -Wl,--version-script,/misc/linux/64/opt/pkg/matlab/R2010b/extern/lib/glnxa64/mexFunction.map -Wl,--no-undefined -fopenmpofopenmp
         LDDEBUGFLAGS       = -g
         LDOPTIMFLAGS       = -O
         LDEXTENSION        = .mexa64
         arguments          = 
->    LDCXX                 = 
->    Link flags:
         LDCXXFLAGS         = 
         LDCXXDEBUGFLAGS    = 
         LDCXXOPTIMFLAGS    = 
         LDCXXEXTENSION     = 
         arguments          = 
----------------------------------------------------------------


Warning: You are using gcc version "4.4.4".  The version
         currently supported with MEX is "4.3.4".
         For a list of currently supported compilers see: 
         http://www.mathworks.com/support/compilers/current_release/

-> gcc44 -c  -I/misc/linux/64/opt/pkg/matlab/R2010b/extern/include -I/misc/linux/64/opt/pkg/matlab/R2010b/simulink/include -DMATLAB_MEX_FILE -ansi -D_GNU_SOURCE  -fexceptions -fPIC -fno-omit-frame-pointer -pthread -I/home/matteson/sundials/include/ -L/home/matteson/sundials/lib -lsundials_cvode -L/home/matteson/sundials/lib -lsundials_nvecserial  -DMX_COMPAT_32 -O -DNDEBUG  "mex_cvode.c"

-> gcc44 -O -pthread -shared -Wl,--version-script,/misc/linux/64/opt/pkg/matlab/R2010b/extern/lib/glnxa64/mexFunction.map -Wl,--no-undefined -fopenmpofopenmp -o  "mex_cvode.mexa64"  mex_cvode.o  -Wl,-rpath-link,/misc/linux/64/opt/pkg/matlab/R2010b/bin/glnxa64 -L/misc/linux/64/opt/pkg/matlab/R2010b/bin/glnxa64 -lmx -lmex -lmat -lm -lstdc++

mex_cvode.o: In function `mexFunction':
mex_cvode.c:(.text+0x2b2): undefined reference to `N_VNew_Serial'
mex_cvode.c:(.text+0x2db): undefined reference to `N_VNew_Serial'
mex_cvode.c:(.text+0x35b): undefined reference to `CVodeCreate'
mex_cvode.c:(.text+0x39c): undefined reference to `CVodeInit'
mex_cvode.c:(.text+0x3dd): undefined reference to `CVodeSVtolerances'
mex_cvode.c:(.text+0x412): undefined reference to `CVodeSetUserData'
mex_cvode.c:(.text+0x449): undefined reference to `CVDense'
mex_cvode.c:(.text+0x482): undefined reference to `CVDlsSetDenseJacFn'
mex_cvode.c:(.text+0x50c): undefined reference to `CVode'
mex_cvode.c:(.text+0x5b4): undefined reference to `N_VDestroy_Serial'
mex_cvode.c:(.text+0x5c0): undefined reference to `N_VDestroy_Serial'
mex_cvode.c:(.text+0x5cc): undefined reference to `CVodeFree'
collect2: ld returned 1 exit status

    mex: link of ' "mex_cvode.mexa64"' failed.

??? Error using ==> mex at 208
Unable to complete successfully.
不知何故,我没有给出正确的标志来正确链接。如果在gcc44命令中删除要链接的命令,则会出现相同的错误集(还有一些错误),因此我很确定编译器不会“看到”库

我的问题是:

  • 如果我对错误的分析是正确的,我需要向mex编译命令传递哪些标志才能成功链接
  • 或者,在Matlab环境之外编译和链接.mex64可执行文件的gcc标志是什么
  • 如果我的分析是错误的,接下来该怎么办
我想我已经排除了不受支持的编译器警告,因为我已经能够使用GCC4.4使用OpenMP程序编译简单的mex,但是这些程序不必与数学库之外的任何东西链接。此外,如果我使用gcc版本4.1.2或4.3.4编译,无论是否使用“-fopenmp”标志,我都会得到相同的错误

最后,我确实需要版本4.4,因为某些OpenMP支持在以前的版本中没有出现

提前谢谢你的帮助

--安德鲁

编辑:(@KWATFORD)

因此,我尝试使用引号外的语句执行该命令,结果出现错误:

-> gcc44 -c  -I/home/matteson/sundials/include/ -I/misc/linux/64/opt/pkg/matlab/R2010b/extern/include -I/misc/linux/64/opt/pkg/matlab/R2010b/simulink/include -DMATLAB_MEX_FILE -ansi -D_GNU_SOURCE  -fexceptions -fPIC -fno-omit-frame-pointer -pthread -fopenmp  -DMX_COMPAT_32 -O -DNDEBUG  "mex_cvode.c"

-> gcc44 -O -pthread -shared -Wl,--version-script,/misc/linux/64/opt/pkg/matlab/R2010b/extern/lib/glnxa64/mexFunction.map -Wl,--no-undefined -fopenmp -o  "mex_cvode.mexa64"  mex_cvode.o  -L/home/matteson/sundials/lib -lsundials_cvode -lsundials_nvecserial -Wl,-rpath-link,/misc/linux/64/opt/pkg/matlab/R2010b/bin/glnxa64 -L/misc/linux/64/opt/pkg/matlab/R2010b/bin/glnxa64 -lmx -lmex -lmat -lm -lstdc++

/usr/bin/ld: /home/matteson/sundials/lib/libsundials_cvode.a(cvode.o): relocation R_X86_64_32 against `a local symbol' can not be used when making a shared object; recompile with -fPIC
/home/matteson/sundials/lib/libsundials_cvode.a: could not read symbols: Bad value
collect2: ld returned 1 exit status

    mex: link of ' "mex_cvode.mexa64"' failed.

??? Error using ==> mex at 208
Unable to complete successfully.
对于使用“-fPIC”重新编译的建议,我有点困惑,因为当我查看gcc44命令时,我将-fPIC视为一个选项

他们是说用-fPIC重新编译库吗

我没有库的源代码,如果建议重新编译库,是否有解决方法

“针对本地对象重新定位”是什么意思


继续感谢。

Matlab使用自己的libstdc和libstdc++

快捷方式是将这些库符号链接到要使用的gcc44库


但这可能不是理想的方式。您可以尝试在matlab提示符外编译,然后首先查看编译是否仍然失败。

尝试不要将
-l
-l
-I
参数放在这些环境变量中。mex函数将直接处理这些类型的参数。因此,也许类似于:

mex -v CC="gcc44" CFLAGS="\$CFLAGS -fopenmp" LDFLAGS="\$LDFLAGS -fopenmp" -I/home/matteson/sundials/include/ -L/home/matteson/sundials/lib -lsundials_cvode -lsundials_nvecserial mex_cvode.c

夸特福德在第二个问题上让我走上了正确的轨道。通过使用共享库重建日晷解算器,我可以使mex命令正常工作。具体地说,我是通过以下方式构建的:

% make distclean
% ./configure --prefix=/home/matteson/sundials --enable-shared
% make
% make install
另外,感谢kwatford通过拨打以下电话修复了原始版本:

mex -v CC="gcc44" CFLAGS="\$CFLAGS -fopenmp" LDFLAGS="\$LDFLAGS -fopenmp" -I/home/matteson/sundials/include/ -L/home/matteson/sundials/lib -lsundials_cvode -lsundials_nvecserial mex_cvode.c

因为mex知道如何处理-L和-I。

我尝试了这个命令,但得到了一个不同的错误(不知道这是否是进度)。我编辑了这个问题以显示新问题。谢谢您的帮助。@Svenless:对不起,如果您没有访问源代码的权限,我不知道如何解决这个新错误。这是一种比我所知道的更神奇的魔法,但其要点是:共享库(如mex文件)需要独立于位置,因为它们将在任意位置加载。您尝试链接的静态库是位置相关的,因此无法在任何ole内存位置正确加载它。它需要重新编译。所以我和我的系统管理员追查了源代码,我们用共享选项重新制作了解算器。它正在工作。感谢您提供了最初的修复程序,并帮助我正确使用这些库。@Sevenless我还在尝试将C代码的makefile转换为mex的makefile。但是,我怀疑我没有正确地进行编译和链接。如果您能看看我的帖子,我将非常感激: