| 
                 
TA的每日心情|  | 怒 2019-11-20 15:22
 | 
|---|
 签到天数: 2 天 [LV.1]初来乍到 | 
 
| 
x
EDA365欢迎您登录!您需要 登录 才可以下载或查看,没有帐号?注册  # {8 w, F9 {. q- t3 I7 |$ D说明
 : m" k) a* q9 K  z% nMatlab混合编程* x) _. p' h( J
 下载与安装编译器
 7 [+ s- Z. I7 j! P5 _. q* d  H$ SMicrosoft Windows SDK 71CC4 Y0 H2 m4 T3 Z" t% K
 TDM-GCCgccg! c8 p6 _4 [. g% [0 u- X
 For Matlab 20153 `) A7 z' p% ^
 For Matlab 2014
 + @$ {( x" z2 u" w/ q# q选择编译器
 + J/ p: `0 F' ~9 u' T编写ccpp文件- L5 L% ^) `8 {+ D
 mexFunction函数介绍
 ; k; h4 Y$ n% Z: f" b7 Q+ b编译多个ccpp文件
 5 S$ Z  |0 ?. n: |一些实例
 8 N2 {' `  [, _! A: d7 jMATLAB2015编译MeanShift
 4 i% u( B8 M  R. VProblemSolution
 4 \! ~+ C" a  d找不到编译器或SDK
 & D3 X: H" m# N. J. dProblem5 a/ ~% M* l5 ^) y; `! K$ e( B
 Solution  a  a, Z6 n& w' }9 o2 e! v4 P
 注意* _* I8 V' }4 H! I
 error C2143 syntax error
 7 D; c( s7 W3 p3 @Problem7 E/ Q* g7 p& @4 Y: |
 Solution8 g1 Y- @! l. C* ^0 j6 H5 C% A
 一些有用的总结% T1 T: U* l) C/ C; z
 注意系统平台和文件路径
 $ p7 T+ F4 o# r& F# V5 }运行效率对比# k" W' A+ ~: H6 n3 m
 说明
 ; b  n9 A* K% x$ [记录本人在Windows下,使用Matlab 64-bit 版进行混合编程时遇到的问题,主要记录编译器的安装与简要的混编过程。  s7 W% j5 F2 ~2 I$ P- e* @9 i
 4 L0 o! w& b9 Q& h) E
 
 8 l% @& ]2 D6 w7 xMatlab版本:Matlab R2014a 64-bit、Matlab R2015b 64-bit操作系统版本:Windows 8.1 64-bit、Windows10 64-bit编译器:Microsoft Windows SDK 7.1(C/C++) 和 GNU编译器(有MinGW(Minimalist GNU for Windows,仅32位)、MinGW64(64位和32位)、TMD-GCC(非官方的编译器包)、CygWin等等,它们间的区别与联系参见GCC_Cygwin_MinGW_TDM-GCC)9 G- z9 L! b/ ~! q9 Y
 
 3 }) E/ c9 p1 K6 Z, ZMatlab混合编程) U8 D, P  [2 y1 u+ B( ]' X( @9 l+ p
 下载与安装编译器
 1 i1 q* l8 U' s+ }Microsoft Windows SDK 7.1(C/C++)
 5 q+ \/ \: A; s8 t8 X& g2 B* Y6 g) d点此Microsoft Windows SDK for Windows 7 and .NET Framework 4 (ISO)打开下载页面,是镜像文件,选择64-bit版,文件大小500M+,全部安装需占磁盘近2G。! _+ e. [+ V# b2 s4 u
 % A0 y8 J" {9 C, v2 {
 下载完成后根据提示安装即可,如果出现问题,安装失败,参考:Problem&Solution 部分。" f. Q' d+ S  o* g- p6 w% {
 
 , b3 f2 N; b2 DTDM-GCC(gcc/g++)
 $ }- A* y$ P7 t' b+ _! \0 B; iFor Matlab 2015! q5 r  Z6 ^$ q' D
 Matlab 2015已经开始支持GNU编译器,具体参见:Supported and Compatible Compilers for R2015b,安装方法参见:Install MinGW-w64 Compiler。; d3 E3 Y( A6 `8 n
 
 . X" A7 X1 E/ B/ c0 C
 注意,MATLAB 2015现仅支持GCC4.9.2,在安装TMD-GCC时,不要勾选更新,如下图:! {8 F4 _4 P: b/ S( ?5 J" G
  # D0 ?. M/ C% u: B 
 然后,还需注意的是安装路径不能有空格;. }- d1 d  o5 u7 |
 - J2 ]; o# c! R1 l8 p9 ~
 需要添加系统环境变量MW_MINGW64_LOC=your tdm-gcc path。重启系统和MATLAB后,输入mex -setup显示:; l7 c- T9 n5 Q" Y+ n* A
   ; E9 u/ @6 d# U/ T( }' K至此完成!
 3 R  ~+ e3 G  |. C7 m' }5 \7 f" h! X! M2 x0 _- z
 
 & i* b3 S3 V) d! Z% P0 VFor Matlab 2014
 % N( W. W0 J- W! Y4 ^6 F如下文章针对于MATLAB 2014a。
 6 M: k$ Z; y; F
 + |& h  C5 J4 @* x9 p" v. ?7 {点此tmd-gcc打开下载页面,选择64位版本,40M+,全部安装占用400M+磁盘空间。
 1 q& Z2 b4 q+ [2 L+ q. F2 Y
 + P: E  _3 d5 \根据以前使用经验,安装路径最好不要有空格中文。
 7 {$ ]3 \, z, B. C* H2 x
 / s! ]; u+ V/ `# g7 R& U安装完成后,开始 -> 运行 -> cmd打开Windows命令窗口,输入gcc -v,如下图所示,显示安装信息,说明安装成功: ; z+ x) f6 @  g+ g+ A! s% }
 
  . a4 Y; [! O1 f7 h( \ " e4 o. ?- _3 E! C9 }7 M
 最后的战斗:
 & K4 m; z7 ~  H$ V$ W6 g因为Matlab不支持GNU的编译器,还得做点事,下面的方法来自Using GCC (MinGW) as MATLAB’s MEX compiler 中的Bogdan的解答:
 : A, D# r( T! t4 w9 D* v4 G* O% D. s0 b% H5 W
 下面的代码是从Bogdan主页上下载的mexopts.bat文件代码,使用时需要做一点小小的改动。" q9 F' h2 ]: Y. i( K- C
 ) G; k0 @( T6 ^/ M) _
 在下面的代码中找到:set MINGWPATH=p:\mingw64这句代码,将其中的路径p:\mingw64替换成你的TMD-GCC-64的安装目录,如我的是:E:\devtools\TDM-GCC-64,然后保存并将mexopts.bat文件copy到计算机如下路径(复制下面的路径地址,粘贴到资源管理器窗口地址栏,回车即可):
 + F8 U) n/ j: r7 D! Y+ d% G" U6 V( Q0 e" @
 %USERPROFILE%\AppData\Roaming\Mathworks\MATLAB\R2014a\* N  I9 [7 Y4 |$ y0 g7 l
 ~5 \/ i! j& X0 Z% ?
 下面是代码:
 j- F0 Z, |* x. h: r2 |9 {7 N. d4 `( k5 P3 s1 o+ l
 @Echo off. J8 r5 G  z5 o* h+ S
 7 Y2 P% [/ L8 W- {5 T" W% N
 :: NOTE: this is actually not a proper .bat file executed by Windows. MEX7 K3 Q) B# c2 X! j8 b
 ::       parses it and only understands a very reduced set of commands:9 S* Y* l* J9 e5 \  g" h
 ::       "set" and "rem" apparently, everything else is ignored (behaves as
 ( {8 t% g. U& I/ N% P::       "rem"), so don't do any fancy batch stuff in here. There are some: X8 x0 l! i! z. ?+ |- K1 d& z$ s4 v
 ::       undocumented special vars you can set here that will trigger MEX
 1 _5 D2 Z! K9 f* ~% E) f::       to do fancy stuff.
 9 {$ l6 D: t: q' J- Z) {
 3 ]6 I$ L9 b" a  X:: You can use MinGW64 builds (win32 threads + seh unwinding) from here:% ]% }- }5 e2 x/ O0 c
 :: http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Personal%20Builds/mingw-builds/
 $ G  }0 _7 k" o2 @$ n0 F. N/ _" y" n. Y$ X6 }
 :: Tested with the following:
 ( {$ j  F, F! T/ o6 n:: http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Personal%20Builds/mingw-builds/4.9.1/threads-win32/seh/x86_64-4.9.1-release-win32-seh-rt_v3-rev1.7z9 q& `& u+ s  s+ A) j" k* H
 
 ! D5 ~2 y# X- ~4 I, j$ K+ S:: Set this to your Mingw64 top folder, where you extracted the above
 ' o# v; v' D6 b% M7 @set MINGWPATH=p:\mingw64' B" o1 J$ l4 h) [5 G$ j) z
 9 c! ?$ p0 a, C$ r2 e9 k% Z$ ]
 :: Leave these alone unless you know what you're doing.
 4 a, ?3 g" f$ d$ I& aset PATH=%MINGWPATH%\bin;%PATH%
 3 l/ J" S+ c* ^8 p2 ~. k: Iset PRELINK_CMDS=echo.>%TEMP%\mexstaticlibs7 d! ~) |# E- ?
 
 ( v; a% j+ }9 s. \% Y+ @:: You can have MEX run some commands before calling the linker.
 / u1 X6 T, X& m; b+ y" @$ m3 c:: The two examples below will cause gcc to output the full path to some
 1 T$ T! I, B; I$ [! ?:: static libraries so you can link statically to them (see the2 _% u6 F* Z6 k
 :: LINGFLAGSPOST special var below). You can set any command here, however.; _' G) o' d1 P, A5 r$ @
 rem set PRELINK_CMDS1=gcc -print-file-name=libwinpthread.a >> %TEMP%\mexstaticlibs
 , @; y) z6 @6 n; i; ~rem set PRELINK_CMDS2=gcc -print-file-name=libquadmath.a >> %TEMP%\mexstaticlibs
 1 h8 P; G( S2 G, {rem set PRELINK_CMDS3=...1 E0 }, q  O$ u; C4 A8 \
 
 % v% [( ?" e: @- S0 ?6 {* q:: You can have MEX run some commands also after calling the linker
 : }  `8 N0 n% ~6 k3 Y6 i" |5 B+ p:: (e.g. upx compress the output .mex)
 6 K7 m7 [+ ?6 R% Z) a0 Brem set POSTLINK_CMDS1=upx -9 "%OUTDIR%%MEX_NAME%%MEX_EXT%"' C- A4 s/ D' a, s4 A. {* e
 rem set POSTLINK_CMDS2=.... R+ l  o8 O* O
 + b4 Y; f0 K2 s6 b
 :: You can change these if you really need to./ S4 }! }! Z! c8 T, }7 t5 s3 f1 c
 set COMPILER=g++, {8 O6 p  P( J& J- m8 T: c
 set COMPFLAGS=-c -I"%MATLAB%\extern\include" -DMATLAB_MEX_FILE
 ; i1 w/ N8 B+ Z( Q# n: X4 g- gset OPTIMFLAGS=-O3 -funroll-loops -DNDEBUG- t" M: r- r) `& y6 o
 set DEBUGFLAGS=-g  [  X, l% c6 q5 O% t1 ?  }* L
 set NAME_OBJECT=-o6 [* b/ F; W2 g, Y! V& w
 
 1 `  X. G! x; H( b6 y, oset LINKER=g++/ K7 y5 ^5 y8 E4 i! v2 h2 r
 set LINKFLAGS=-shared -static-libstdc++ -static-libgcc -L"%MATLAB%\bin\win64" -L"%MATLAB%\extern\lib\win64\microsoft" -lmex -lmx -leng -lmat -lmwlapack -lmwblas" z: p4 n: O, X4 I2 H/ b
 0 k8 Q$ [' P# m- t
 set LINKFLAGSPOST=@%TEMP%\mexstaticlibs
 8 x% M( j7 T$ f- ^! A# Iset NAME_OUTPUT=-o "%OUTDIR%%MEX_NAME%%MEX_EXT%"# `2 o- y% O, b1 m7 R; s
 1 @: k  r4 z7 V9 A
 * R, V- O$ U5 v( H+ a
 :: EXAMPLES
 ' ~  W- _. r0 y% X# R:: ========
 1 o# O( P3 H% a- ?/ ~) s+ w/ v% |# ]# R$ P- l4 V% ]+ l
 :: You can compile simple files using "mex file.cpp". To support more than 2^32 elements, use9 b/ W# `: I+ D
 :: "mex -largeArrayDims file.cpp" ... use this by default, unless you know what you're doing.9 o$ K9 q: q. a* ?' i, P! p
 : y% ^2 [  s4 ]/ s4 M. R) j0 R
 :: To add include dirs, lib dirs, or compile/link flags, do:
 5 j; a0 H) D- E, b/ c+ m9 w8 `:: mex COMPFLAGS="$COMPFLAGS -std=gnu99 -Ix:/include/dir" LINKFLAGS="$LINKFLAGS -Lx:/libs/dir -lmylib" -largeArrayDims file.cpp" E2 }( ^  b2 u- n& I0 ?% Q1 |, J
 ) J0 y) M# @2 T1 W: u1 @; U
 
 : f; U; M- e; [  m- V( j选择编译器6 D9 ^8 b, U# d4 G& u- e
 查看可用编译器:使用mex -setup查看可选择的编译器,如果没有需要自己安装,如果已安装且只安装了编译器Microsoft Windows SDK 7.1(C/C++),显示如下结果: 5 \3 ?7 S! g* C/ K7 @
 
  5 \# d3 f  H+ W* M: I4 A 选择编译器:使用mex -setup lang选择编译器,如mex -setup C++选择C++编译器,如下图: ! j9 u4 F% V% [) [
 
  3 h* \( R9 }. ~* a1 S% g 如果你也按上面TDM-GCC(gcc/g++) 中讲的方法,配置了TDM-GCC-64位的编译器,那么,你会发现结果如下: 3 d; @' P( c9 g
 
   ?+ u5 b, t" |+ g. Y: w- r9 Z' |3 m' I2 t! i8 W
 刚开始我也以为不能用,后来试着编译了一下,竟然可以!
 9 B+ T) d1 T+ d3 n$ T8 z
  3 E  z0 m* R9 Y' D1 j 
 * v) I% g  N' q: L0 lDT.c文件中重复定义了无穷大,注释掉,就没有提示啦!
 4 A0 a6 e" X9 f& i* O; V- O  n0 n) ^7 N& @5 c/ J
 
 6 Q% ?: W+ Q7 |' A6 ?& d% u编写c/cpp文件
 ! q- ~, ?8 ?; C: T) p/ ]( v& ?/ E
 0 [8 s! _6 a: r/ e* q与普通的C文件的编写有两点不同:
 " P) x! [& |% V/ b% j, ~3 z9 m
 , k. P6 t5 W# _. }9 n
 # H- B. L4 b8 K8 P$ \3 j包含mex.h头文件,即:#include "mex.h";编写mexFunction函数。+ @5 k  o: L5 I% h6 x
 下面以一个求和的例子说明:
 3 g  X: R# E5 `7 t! z; [: `; p; s# |1 C$ y
 Q( A* ]7 S% C: [" Q( W. q$ Q#include "mex.h" // 使用MEX文件必须包含的头文件
 3 n  j4 w) n4 \// 执行具体工作的C函数
 6 d2 t! e+ v- p1 d0 _) m7 M# y, r) _double add(double x, double y)
 2 b$ g; c$ a! n$ v& }{
 ( F) \! e* H( o# _/ P    return x + y;# ]9 c- V! z  F$ L2 i$ M* [
 }
 * u' M5 j4 S: v) ~' ~* @// MEX文件接口函数# b' e) s8 p4 R+ ~. o. l2 _# X! r
 void mexFunction(int nlhs,mxArray *plhs[], int nrhs,const mxArray *prhs[])
 " U' T* C) [$ J$ ?: ^# g{
 . G; R+ O2 \+ C! B- R4 Y& v) I    double *z;" _! R* ?3 W6 n
 double x, y;
 6 F/ A; @6 Y, G    plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);
 ) Q. V$ F2 C  W+ l7 o    z = mxGetPr(plhs[0]);" ]( t! k+ W* D' }( q
 x = *(mxGetPr(prhs[0]));
 $ b3 y) x& _$ c. P& V6 B6 ?$ g+ B    y = *(mxGetPr(prhs[1]));; K" S' j) F* n* w0 i$ K1 w2 ^
 *z = add(x, y);' b/ t2 G$ B( z, c& M3 i
 }
 ( t. C+ w  ~' B
 0 G' l3 P$ H6 o- p  }5 v& B! {. _0 x6 }  q
 Matlab命令窗口输入mex add.cpp,运行结果如下图: 9 b5 t& X& Y; _& G% B) s+ f. ]
 
   5 v. I( x7 e* R" |+ E
 % v" @' S6 V4 z1 j在Windows上编译后生成mexw32和mexw64文件,在Linux上编译会生成mexa32和mexa64文件。4 X9 H+ z- n3 H4 a- d5 c
 
 . d' X( }  E: R6 K4 D( V3 dmexFunction函数介绍
 7 t1 X0 d* O$ U% SmexFunction函数接口如下:
 5 D" B  k8 A; N; B
 0 b" @2 E! j: ]# @void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
 ! `6 f; P7 v& n, M% y* [. Y: W* a& H9 I
 可见,是没有返回值的,其实是通过指针数组plhs传递的。它共有四个参数,即左边的输出参数及数目和右边的输入参数及数目,具体参数意义如下:
 ; |  Z$ a( F5 @  g6 V9 _( R# w* G9 I& P2 H) i: B6 c" c  a
 参数        意义        英文全称        类型: Q3 v( E8 `, O! D+ x9 C
 nlhs        左边输出参数的数目        number of left-hand side        整型(int)
 U& ?  B7 v% ^plhs        指向输出参数的指针        pointer of left-hand side        指针数组
 5 G1 c& a& w& Dnrhs        右边输入参数的数目        number of right-hand side        整型(int)
 P% d( s. S' A# ^+ G& g: Q( wprhs        指向输入参数的指针        pointer of right-hand side        指针数组' {( a) z7 P+ r" q) G  ]- q
 详情参考:
 ) L. r( U: ?! P6 J) `5 Q& c1 S, ]* f  ^& I
 Matlab参考-MEX库% R- ~  G( s) |( d- Z6 L5 z
 4 H' |8 c0 \! _5 v
 MATLAB中mexFunction函数的接口规范(转载)
 . y* n. B/ m) y+ s0 f" G# [/ l2 Q$ @
 3 ~6 }0 j. c) \) j" DMatlab与C语言程序的应用编程接口5 L6 @- q6 W* x4 Z  l& S
 
 3 R/ ~( @$ o9 A$ m. F: w- qmatlab和C/C++混合编程–Mex
 $ W% c/ ^1 b6 O- I
 5 C# v, M! ^6 v; b$ z- j编译多个c/cpp文件
 8 o6 U* W. \4 M7 |% ]& K. b. I8 K假设A.c调用B.c,B.c调用C.c
 ( r" R5 D& E. f. A& m+ I: A4 m9 O可以使用如下命令编译:. |; r9 E0 a6 n( b$ I) |- H
 
 5 Q" k4 [& @& I3 t+ lmex C.c- t3 p1 q+ ~  r( W: ?$ E1 u
 mex B.c  ?2 R/ x$ \4 l! a! x- u/ R
 mex A.c' C- W! C7 D. ]+ ^5 X( h/ i7 }
 ' m8 `1 H% y! o
 
 : U) o! L- I0 h% \/ ]或者
 . b7 x+ v$ B2 g; t' }
 , r% w, O& e: {9 P$ z. Bmex A.c B.c C.c
 / r, W2 E. u" |3 w6 c; I  k
 | 
 |