|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
说明
" a; E$ c9 W* ?6 h ]# R1 tMatlab混合编程2 n+ |& d0 V: m; C7 Q% ?
下载与安装编译器
& d" _ F1 h( m F1 g9 Q Microsoft Windows SDK 71CC G$ R% x# K/ H& F4 }/ k* t
TDM-GCCgccg
8 s; }: B' D+ a s3 p/ f For Matlab 2015% Q0 u! W4 {' A0 b
For Matlab 2014
- H8 \7 {4 P% b- x 选择编译器0 P. x* A; D* e; D- [/ _# ?
编写ccpp文件
* V- N5 N4 ?! o! I mexFunction函数介绍* T& z. a$ C5 {
编译多个ccpp文件
$ v( I2 E! H1 b( T. n% s5 k& y$ _6 g0 [0 m9 z4 d9 }
" L7 v* b M* R( V J# e
说明
: z" N" y V4 Q3 `4 z; \ W% `1 X9 ?记录本人在Windows下,使用Matlab 64-bit 版进行混合编程时遇到的问题,主要记录编译器的安装与简要的混编过程。! M' H+ G7 v6 d+ E+ C
0 q! `% L+ W3 P. H, t- Matlab版本: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)6 X8 a# Z/ W5 R0 q- m
1 N5 f1 t+ X" @: j% R
7 t: e% s8 `- u) _. G }- |! P, E% T3 @) S& h& x' H
Matlab混合编程- G, _* X, {3 U* }
下载与安装编译器8 c9 b `; K4 w
Microsoft Windows SDK 7.1(C/C++)
. t# b" ]" D/ P% x点此Microsoft Windows SDK for Windows 7 and .NET Framework 4 (ISO)打开下载页面,是镜像文件,选择64-bit版,文件大小500M+,全部安装需占磁盘近2G。
, E1 _9 T: I% |/ O6 i2 N9 E/ }
4 A' }5 H. @. |$ K下载完成后根据提示安装即可,如果出现问题,安装失败,参考:Problem&Solution 部分。
& N" p# A2 B6 Q/ k) X+ Y
. z( E% X1 j7 vTDM-GCC(gcc/g++)
% `% A) g( a' c$ E" D; w* JFor Matlab 20152 q9 o v" n. f6 K x7 `
Matlab 2015已经开始支持GNU编译器,具体参见:Supported and Compatible Compilers for R2015b,安装方法参见:Install MinGW-w64 Compiler。
9 u3 w6 {7 L$ f2 g4 O! w
- K+ u7 ]/ Q G/ m6 c0 j- 注意,MATLAB 2015现仅支持GCC4.9.2,在安装TMD-GCC时,不要勾选更新,如下图:
" b( v0 u7 T* {! F* C 6 b6 K. Y- c! E- e
. M; i* b6 {% b9 B
" k; s4 |" f/ T% T- 然后,还需注意的是安装路径不能有空格;
- 需要添加系统环境变量MW_MINGW64_LOC=your tdm-gcc path。
- 重启系统和MATLAB后,输入mex -setup显示:
, ~, a. M8 B5 u0 m9 U' h3 W
' H8 A; P: R5 N" Q, F
4 j9 V% }6 A" G Q3 z! v
p4 Q' p8 r/ `$ K3 W至此完成!
1 E( Z. @( ], e
7 v" e4 [: I4 B7 J+ IFor Matlab 2014
0 P8 z" P4 Y, ^1 U: C6 i3 h, [如下文章针对于MATLAB 2014a。
" [! H+ f# r+ b( T0 n! l1 F
- I# O% h, {0 K4 a4 A, L点此tmd-gcc打开下载页面,选择64位版本,40M+,全部安装占用400M+磁盘空间。* E# \7 k9 U+ j& i
$ Y( B5 `* A ]% X' n' w) G
根据以前使用经验,安装路径最好不要有空格中文。7 X" b% B2 i$ r( X# r4 a. h
0 c+ W4 ^5 y" @9 ?" S8 A
安装完成后,开始 -> 运行 -> cmd打开Windows命令窗口,输入gcc -v,如下图所示,显示安装信息,说明安装成功: ( ]& e( d o: e7 D7 R* `) |
! ^0 `: U( C* h8 r, I
M- O* a1 d! u; |# H最后的战斗:
4 X0 v6 e5 t' e; a* |因为Matlab不支持GNU的编译器,还得做点事,下面的方法来自Using GCC (MinGW) as MATLAB’s MEX compiler 中的Bogdan的解答:
) N% M2 y- d+ Y3 U1 A" X1 m7 ^1 o2 K3 P( l7 x5 }4 z. n, P
下面的代码是从Bogdan主页上下载的mexopts.bat文件代码,使用时需要做一点小小的改动。2 V7 o! a0 R: o& B
7 ~. e+ p( i" {: ]
在下面的代码中找到:set MINGWPATH=p:\mingw64这句代码,将其中的路径p:\mingw64替换成你的TMD-GCC-64的安装目录,如我的是:E:\devtools\TDM-GCC-64,然后保存并将mexopts.bat文件copy到计算机如下路径(复制下面的路径地址,粘贴到资源管理器窗口地址栏,回车即可):) t" N; a2 G( p- D
! f z' S- ^4 j; _% ^/ }1 E% U
%USERPROFILE%\AppData\Roaming\Mathworks\MATLAB\R2014a\
7 ]0 O$ [& d$ n( o. d$ W2 B8 Q- }2 B4 F" E, d4 `6 [. a
下面是代码:
) |, I O: V9 Y# `0 |3 O+ Q0 |9 r" n) ~, B; N5 y. Y
@Echo off3 ^5 v7 t+ U/ k
3 |$ o' B& H8 Q$ l9 W/ d( J
:: NOTE: this is actually not a proper .bat file executed by Windows. MEX
4 E" f" @9 R3 I:: parses it and only understands a very reduced set of commands:
" C$ u" S3 V( c" U:: "set" and "rem" apparently, everything else is ignored (behaves as9 T7 B; t, }, a! u' R
:: "rem"), so don't do any fancy batch stuff in here. There are some& w3 Y8 y" U- t C& B* [
:: undocumented special vars you can set here that will trigger MEX+ y) b+ b1 W6 M+ w! C7 w" t( r2 c
:: to do fancy stuff.
* P/ ~3 l& j0 i/ \/ T( D5 U
: x# L6 B( |7 o0 a- y:: You can use MinGW64 builds (win32 threads + seh unwinding) from here:
x3 _; @4 T% d* `; c:: http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Personal%20Builds/mingw-builds/, \9 p9 B8 e" K% V
( N5 l5 `1 ?2 Q, [8 u/ [& \:: Tested with the following:, z3 s- Y' S5 ~6 K9 |- v' s" i4 q
:: 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.7z! L2 w; n6 I5 g, Z9 g# [" N
9 x0 k+ @7 b' }
:: Set this to your Mingw64 top folder, where you extracted the above6 }9 O! a/ x( k. H
set MINGWPATH=p:\mingw64
4 `3 o1 g8 D4 ~/ m e
7 x) A* q/ R% G% U5 r! v3 M% _:: Leave these alone unless you know what you're doing.7 B1 f. m9 P& R8 {2 Q
set PATH=%MINGWPATH%\bin;%PATH%
4 T1 J' C6 A; T4 R; y! e, Uset PRELINK_CMDS=echo.>%TEMP%\mexstaticlibs
. w( }: R1 k+ n+ }4 D/ B- D' O3 E* K+ ~8 o
:: You can have MEX run some commands before calling the linker.: l9 d7 C+ A! W, u2 |
:: The two examples below will cause gcc to output the full path to some
5 }5 _+ Q( p( z% @, J:: static libraries so you can link statically to them (see the
/ O" v, q6 ]' q8 J' R:: LINGFLAGSPOST special var below). You can set any command here, however.
5 r( H: Z0 h, U* o# }rem set PRELINK_CMDS1=gcc -print-file-name=libwinpthread.a >> %TEMP%\mexstaticlibs
9 S* n/ R3 q) g9 }rem set PRELINK_CMDS2=gcc -print-file-name=libquadmath.a >> %TEMP%\mexstaticlibs
/ W. x, a8 x/ x& [/ Drem set PRELINK_CMDS3=...
$ W. ~) c% s( J& g6 c8 \% G* t5 [& r: X [2 I
:: You can have MEX run some commands also after calling the linker# Q! m4 }/ W5 s/ w: g+ y" j9 a3 v
:: (e.g. upx compress the output .mex). r& r% u& [. A' Y
rem set POSTLINK_CMDS1=upx -9 "%OUTDIR%%MEX_NAME%%MEX_EXT%", d8 x" p1 q4 A6 n9 E
rem set POSTLINK_CMDS2=...0 j: K% u$ n I
! o9 W: ?. ]* M/ M- `
:: You can change these if you really need to. S5 c/ ?) I% D8 N
set COMPILER=g++6 p) a9 t6 g- q
set COMPFLAGS=-c -I"%MATLAB%\extern\include" -DMATLAB_MEX_FILE6 z1 m7 V6 b2 N
set OPTIMFLAGS=-O3 -funroll-loops -DNDEBUG! i1 X% V5 ]4 X$ [1 V0 \9 u5 ~+ L
set DEBUGFLAGS=-g
! |% }6 a/ k- D. m/ Bset NAME_OBJECT=-o4 ~! b- ~* |( T" i& I
( R8 n5 N, F6 g/ Z. {2 R
set LINKER=g++. k3 Y5 q9 n( R9 w3 Y
set LINKFLAGS=-shared -static-libstdc++ -static-libgcc -L"%MATLAB%\bin\win64" -L"%MATLAB%\extern\lib\win64\microsoft" -lmex -lmx -leng -lmat -lmwlapack -lmwblas
9 X- S- A4 N4 ?2 [2 |/ y' R1 {3 o! @: b" c* M
set LINKFLAGSPOST=@%TEMP%\mexstaticlibs
0 Q+ ^1 L" u. ~3 H0 ~2 J2 Dset NAME_OUTPUT=-o "%OUTDIR%%MEX_NAME%%MEX_EXT%"
' a3 C0 f- M7 h! ?( n: B* Z9 z% G* U i2 [/ ?
, h8 S* I' _& F6 [1 s* m* \:: EXAMPLES
* V* i8 P( p: T% R4 `:: ========
( Z# P4 C1 z8 K8 Q' `
6 ^3 ^' w1 }8 ~:: You can compile simple files using "mex file.cpp". To support more than 2^32 elements, use& z1 R! m9 G/ I, W
:: "mex -largeArrayDims file.cpp" ... use this by default, unless you know what you're doing., R' A- n% m) r: Y9 S' T4 j* t
/ |- s1 S( d! Q
:: To add include dirs, lib dirs, or compile/link flags, do:8 G* o+ X, O2 g5 _4 f7 ]* L5 p8 F
:: mex COMPFLAGS="$COMPFLAGS -std=gnu99 -Ix:/include/dir" LINKFLAGS="$LINKFLAGS -Lx:/libs/dir -lmylib" -largeArrayDims file.cpp% M4 V: S4 X7 {/ X
7 e: w$ c7 D+ C' V8 ]9 ~
# d+ T4 J3 Q/ c: U% M
选择编译器
) R) U9 P! V- Y" ^7 Z3 j S- 查看可用编译器:使用mex -setup查看可选择的编译器,如果没有需要自己安装,如果已安装且只安装了编译器Microsoft Windows SDK 7.1(C/C++),显示如下结果:. v+ j$ s3 a I- q! F
- 选择编译器:使用mex -setup lang选择编译器,如mex -setup C++选择C++编译器,如下图: ! Y/ ^2 @2 ? E0 ]
- 如果你也按上面TDM-GCC(gcc/g++) 中讲的方法,配置了TDM-GCC-64位的编译器,那么,你会发现结果如下: , i7 M7 U; i- T6 ]& W& F
|: i. m& R% [
* F& ^* ]# Y* {9 o/ i3 F6 a# Z
C& D- v/ V, ^. ]
刚开始我也以为不能用,后来试着编译了一下,竟然可以!
" A2 L) N* M" a% l ?! Z
; O$ F: n! d6 ^1 w" ~" wDT.c文件中重复定义了无穷大,注释掉,就没有提示啦!, j0 X) G: G8 | s
: _+ a. s+ f* M. d, R: ^/ `
: n. v7 E4 @& ^8 E9 _0 m- [
编写c/cpp文件
" ^( t3 ]9 H5 N. G! F0 U. }与普通的C文件的编写有两点不同:
( @# v7 z( k9 y1 ?9 O
8 e y% M" X/ g; U1 g- 包含mex.h头文件,即:#include "mex.h";
- 编写mexFunction函数。
- g4 R: [! S1 [) d- d: S
7 Q6 P0 Z5 Y0 ?# e5 W& [" _0 Z) O$ r' Q& G
下面以一个求和的例子说明:- r; L% E% {! r, z$ \0 u
, W6 B) g- _. W5 r, K+ A#include "mex.h" // 使用MEX文件必须包含的头文件
' Y" Q. |0 ]+ s1 z% T// 执行具体工作的C函数* _' Z, T# `7 {" v
double add(double x, double y)" l6 I. _! V2 x6 L# O2 x
{
, a# P+ d! Y% K' }" U) u7 D return x + y;0 }2 t+ k- L: H2 x8 C6 A% H! z8 {) K
}6 Q9 I( [1 M! A: J% s4 V
// MEX文件接口函数
+ {3 C4 A! |* q. qvoid mexFunction(int nlhs,mxArray *plhs[], int nrhs,const mxArray *prhs[])
7 P1 v$ I. _4 M$ w{
. H7 l4 |2 W& J double *z;: T* u' l# ^( {
double x, y;
* M1 P- k0 q; }' x: r1 ?/ k, D plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);+ N3 d4 W% u ]. v
z = mxGetPr(plhs[0]);1 b& d* p: h# D! K3 T' q
x = *(mxGetPr(prhs[0]));5 i8 E# o7 Z% _' t& T. |" n, T
y = *(mxGetPr(prhs[1]));! i. A8 K y: E. H; A" l( w$ r
*z = add(x, y);
|- P- I- t9 D}
% L: d- G* W& ` n9 E3 V; F! N* W- P5 H5 ~, I Y0 n
6 Z# |6 O) F) E+ v& q' U$ d
Matlab命令窗口输入mex add.cpp,运行结果如下图:
( |9 |8 K# x/ E' t! e( V. }7 J0 V
; n1 L/ J: J D1 A W
# x& n% ^+ O* G5 E- ]5 \在Windows上编译后生成mexw32和mexw64文件,在Linux上编译会生成mexa32和mexa64文件。- C }, I4 F7 U
5 n; k* Q; w) V8 C9 e6 q
mexFunction函数介绍
3 A! a; d! ~0 q9 [7 NmexFunction函数接口如下:
8 J+ X3 C* `' y5 P- O" Q- X+ e* U; `+ A0 S& w7 u( w
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])7 y3 k5 |8 G7 W2 w7 U$ H
5 R6 Y5 Q2 }, m: {' }# I
可见,是没有返回值的,其实是通过指针数组plhs传递的。它共有四个参数,即左边的输出参数及数目和右边的输入参数及数目,具体参数意义如下:# O5 h2 C# ~) M( i
" K, W$ C+ z: J* ]5 l* L# S
参数 意义 英文全称 类型" t' F( o+ v, Q5 A, R+ W9 l5 F
nlhs 左边输出参数的数目 number of left-hand side 整型(int)/ ]& N1 c9 E& {" x4 u
plhs 指向输出参数的指针 pointer of left-hand side 指针数组' J) K( l$ `" _% q( W6 `0 `/ B- v4 i
nrhs 右边输入参数的数目 number of right-hand side 整型(int)9 ` F. P, k& n
prhs 指向输入参数的指针 pointer of right-hand side 指针数组5 N" p m7 L4 I" a5 f9 O7 L) N' ^
P6 U* o/ j1 |/ [! }8 I- |9 f详情参考:: x8 E# G. _, x- w1 N
# m3 _5 [( ^2 r
- Matlab参考-MEX库
- MATLAB中mexFunction函数的接口规范(转载)
- Matlab与C语言程序的应用编程接口
- matlab和C/C++混合编程–Mex4 H/ h; p3 C* C
! s' n* Z' s; ]: n, R- D. K
8 @: p4 [% M/ \
编译多个c/cpp文件- h) {6 i" J* a/ l
假设A.c调用B.c,B.c调用C.c
: J0 U. W7 c9 _! D$ i" U可以使用如下命令编译:
) [5 o# F* t K8 m
) n3 r0 C& K X: ?" [+ i N* ]8 b0 U* _mex C.c" D( j/ K" G* p+ a C" x$ H3 r
mex B.c4 U' P6 a$ X+ N- Y' ~
mex A.c
4 X2 P# ]2 K3 E$ A' u
: R) m; e" H$ L或者! c$ [! @0 ]8 z1 X: P
: C' B8 }+ k7 \( I' ?mex A.c B.c C.c1 ?0 A; x3 u9 J: M6 |- R- ^
$ V8 j9 H& {- s$ \+ c: o5 |; B5 o; x, ?( `
! R8 p" W1 b e7 N: T9 p9 a
/ c% X! m1 J: g
& E# q- ^7 a% P/ p" i: \6 s4 F/ [# x+ q7 V1 y2 ?2 A2 H
|
|