|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
说明
" l( W' ^, t2 FMatlab混合编程. z: O% J7 q/ c, r$ G/ Y
下载与安装编译器
, ^& P( x y. n: i7 u2 C- ` Microsoft Windows SDK 71CC
- ^8 L9 N+ v: X TDM-GCCgccg, r- N5 G! h8 w
For Matlab 2015) O+ R, Y& t* K; M, i+ b; y
For Matlab 20147 y7 E# i/ k+ Z% Q: \9 `
选择编译器6 a6 K$ B5 E( v0 }: d
编写ccpp文件; G9 f1 B ]; N# q) M$ w
mexFunction函数介绍
* y8 i/ N5 A& F8 u0 n 编译多个ccpp文件+ H7 \$ R3 e, |) P R, `5 b- b
6 k: d s4 h4 G' N9 p9 e6 t3 B, I% J' H v( R' ]; U- ~- _
说明) p/ o! u9 x( Y- x
记录本人在Windows下,使用Matlab 64-bit 版进行混合编程时遇到的问题,主要记录编译器的安装与简要的混编过程。. n! y N. m" b" I4 n
+ a# [( N, [- [$ \$ Y, u Z
- 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)
) R {# D$ M2 ~& n ) u1 a, K7 [8 a; G) i1 F
& {2 o H, N3 h$ m9 n+ G
1 L4 v5 S3 |, h# Q+ Z: r. C4 h% j: lMatlab混合编程
- `3 c- Q1 v0 x. g" G0 A下载与安装编译器' F- t/ ]6 d( x! ~2 n% C: t
Microsoft Windows SDK 7.1(C/C++)# J% F; T6 b0 y. x% h
点此Microsoft Windows SDK for Windows 7 and .NET Framework 4 (ISO)打开下载页面,是镜像文件,选择64-bit版,文件大小500M+,全部安装需占磁盘近2G。
. f9 n2 E7 y; J: V* d K9 Z+ J
) E6 ?; f, b& u# a下载完成后根据提示安装即可,如果出现问题,安装失败,参考:Problem&Solution 部分。7 a, P- j( N. Y4 F6 O
$ _6 B" W4 o% K" ^
TDM-GCC(gcc/g++)4 A) |/ t n R+ M+ _6 Q% e# \ R/ Q1 t* y
For Matlab 2015( ]; d$ C# s6 f
Matlab 2015已经开始支持GNU编译器,具体参见:Supported and Compatible Compilers for R2015b,安装方法参见:Install MinGW-w64 Compiler。
9 `" T& i$ n5 s+ l
* \3 G) v! z5 S* A- 注意,MATLAB 2015现仅支持GCC4.9.2,在安装TMD-GCC时,不要勾选更新,如下图:, S( s# q. ?4 B3 K6 X
' t% _1 R% c) g
. N) ]1 _ G( K* T
, H1 E' n; |& j, N$ T- 然后,还需注意的是安装路径不能有空格;
- 需要添加系统环境变量MW_MINGW64_LOC=your tdm-gcc path。
- 重启系统和MATLAB后,输入mex -setup显示:% h+ _ X, B( S4 b! {' H2 o" h
, K. q- j% Z1 w* k8 t
; I& ^7 B6 j4 \4 R2 d$ Z& h3 v1 O
! _7 ^/ d2 l2 H5 z至此完成!
- g3 c3 ]; I$ c) F q
2 f; ~+ Z: m, j- C. rFor Matlab 2014$ F+ r% ? Q# p. S% l
如下文章针对于MATLAB 2014a。
. F8 c2 z3 W+ ~5 a. e
7 [$ c5 V) S. z7 i) x, }点此tmd-gcc打开下载页面,选择64位版本,40M+,全部安装占用400M+磁盘空间。
, m% N3 ]& @9 R. s" P4 Y
; E$ [* P8 a9 {$ {9 g/ U/ w( `根据以前使用经验,安装路径最好不要有空格中文。* P" r: W0 j- N- C- K0 f
1 l: e! D- @* X4 _. Z* }- T
安装完成后,开始 -> 运行 -> cmd打开Windows命令窗口,输入gcc -v,如下图所示,显示安装信息,说明安装成功:
7 Q) @* [' l6 G0 y# o4 p
2 P7 r9 z' R: m2 k7 w$ u7 e
$ J, M5 z1 y. ]; y最后的战斗:
/ u4 F; _. H; y* l* c% g: [因为Matlab不支持GNU的编译器,还得做点事,下面的方法来自Using GCC (MinGW) as MATLAB’s MEX compiler 中的Bogdan的解答:3 y v3 q/ Y7 k4 N3 c
7 l1 y* r: C7 X h
下面的代码是从Bogdan主页上下载的mexopts.bat文件代码,使用时需要做一点小小的改动。. c3 Q5 x2 K0 ~3 Y& n+ n* O' c
0 ?; ], K% c% G8 A在下面的代码中找到:set MINGWPATH=p:\mingw64这句代码,将其中的路径p:\mingw64替换成你的TMD-GCC-64的安装目录,如我的是:E:\devtools\TDM-GCC-64,然后保存并将mexopts.bat文件copy到计算机如下路径(复制下面的路径地址,粘贴到资源管理器窗口地址栏,回车即可):
e6 O o* L4 R( A# b( |7 ^3 y3 x' \! }0 |/ Z
%USERPROFILE%\AppData\Roaming\Mathworks\MATLAB\R2014a\: }6 E4 A% U; d1 `
% B+ a4 M+ C/ P4 G% s+ o
下面是代码:
W# E# Q7 x, G, S1 }% `! D! I& R/ A1 F4 A) p
@Echo off- K/ u$ v: _2 q& |! b1 j! C
+ c* p* E: `/ p+ r' r:: NOTE: this is actually not a proper .bat file executed by Windows. MEX
5 \6 T9 @: u' t4 u:: parses it and only understands a very reduced set of commands:, r) b) q6 b7 |& _, u" ~+ Y
:: "set" and "rem" apparently, everything else is ignored (behaves as/ L! _9 @9 \& f& @# u" z
:: "rem"), so don't do any fancy batch stuff in here. There are some
* m" n" o3 j/ T# }:: undocumented special vars you can set here that will trigger MEX) O/ d. n' J3 e! X: L
:: to do fancy stuff.
: _ T) s6 {4 p5 A
& } z) v' s, v+ S9 c# |5 p/ T7 D:: You can use MinGW64 builds (win32 threads + seh unwinding) from here:1 ?0 _1 }7 e a$ j7 j6 e4 L
:: http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Personal%20Builds/mingw-builds/2 G# @8 v$ j; _' e3 l9 r
" Z) m8 a# F; Z6 L: R:: Tested with the following:
; X) w5 x0 G2 k. S1 D% a6 W:: 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.7z6 U8 X! E0 j, k3 {8 P
( A! H0 |) Z+ n
:: Set this to your Mingw64 top folder, where you extracted the above: g8 J8 j+ C" \- E7 z# a* R& R
set MINGWPATH=p:\mingw646 r4 ~) n4 @' E! e4 ]# ]
- P& @( T H0 b: ~* w
:: Leave these alone unless you know what you're doing.& q! N0 D- [ Q2 K. m
set PATH=%MINGWPATH%\bin;%PATH%
- N9 n* w; Y$ O: T: L: hset PRELINK_CMDS=echo.>%TEMP%\mexstaticlibs+ l' Y$ g0 r0 A2 `' v6 J
; E' H$ u4 x: ~; e& l+ h) o
:: You can have MEX run some commands before calling the linker.
: [8 d. b2 q8 k% V! V2 z2 W5 r:: The two examples below will cause gcc to output the full path to some
& h4 X; V: }" S' q:: static libraries so you can link statically to them (see the% U& b0 f. M- a+ k' c/ B9 H5 e
:: LINGFLAGSPOST special var below). You can set any command here, however.# W, K2 \; e$ `: {% {
rem set PRELINK_CMDS1=gcc -print-file-name=libwinpthread.a >> %TEMP%\mexstaticlibs; Q X2 }# ]4 b% u! p/ M
rem set PRELINK_CMDS2=gcc -print-file-name=libquadmath.a >> %TEMP%\mexstaticlibs
$ a* Q- k3 M) `- T! u9 B+ Wrem set PRELINK_CMDS3=...
+ x4 F3 N! b, X6 t8 I% s6 o" c& ^0 y6 p( w/ w! h
:: You can have MEX run some commands also after calling the linker
+ A' I" v- O) c& {+ n* n: N:: (e.g. upx compress the output .mex)
6 w9 U8 x4 M2 D* |3 b5 y& _# mrem set POSTLINK_CMDS1=upx -9 "%OUTDIR%%MEX_NAME%%MEX_EXT%"4 m# E6 c/ @: |, I, @7 [$ ^7 ?
rem set POSTLINK_CMDS2=...
, L+ L1 C! M/ @0 C+ G, |" P5 l: `5 w5 |2 b B1 r
:: You can change these if you really need to.8 v( G. }4 s8 e. `: J7 f
set COMPILER=g++$ a( C+ E/ K* p+ k4 J
set COMPFLAGS=-c -I"%MATLAB%\extern\include" -DMATLAB_MEX_FILE
5 d) |5 M) I6 \5 g5 B9 N! Q* Lset OPTIMFLAGS=-O3 -funroll-loops -DNDEBUG# d5 P* ~" Y0 o1 k$ X, F/ y/ f
set DEBUGFLAGS=-g
( G2 X6 h8 K; }3 k$ \set NAME_OBJECT=-o
, E6 X3 `* n" L6 b' v2 t9 F+ D7 o5 M& E! L; k+ m' d9 H! }
set LINKER=g++
! B% j' O; F0 Y( o4 e/ }9 rset LINKFLAGS=-shared -static-libstdc++ -static-libgcc -L"%MATLAB%\bin\win64" -L"%MATLAB%\extern\lib\win64\microsoft" -lmex -lmx -leng -lmat -lmwlapack -lmwblas
( w6 v. \: o @+ I
8 g) _2 V- n R: w2 Oset LINKFLAGSPOST=@%TEMP%\mexstaticlibs B4 A3 A; g; N3 D" i9 u
set NAME_OUTPUT=-o "%OUTDIR%%MEX_NAME%%MEX_EXT%"
, _' @3 Q/ J) d% P. }8 w+ ?! B" \$ ?5 D5 U+ |" m
1 v( ]$ P. G8 T0 e0 B- H
:: EXAMPLES
' v1 e( L+ _$ E: W6 ]1 @:: ========
' B' c* S% j* Y: b. ]5 w( n; E0 x- C1 @* I
:: You can compile simple files using "mex file.cpp". To support more than 2^32 elements, use8 }/ R' Q( n4 T8 @! c/ D
:: "mex -largeArrayDims file.cpp" ... use this by default, unless you know what you're doing.
+ H8 D! Q+ i6 Y( ?: y7 J
3 c. }- j& f, p, H+ P:: To add include dirs, lib dirs, or compile/link flags, do:; E* u" q5 c; ^) B* s: }. ^' U; w
:: mex COMPFLAGS="$COMPFLAGS -std=gnu99 -Ix:/include/dir" LINKFLAGS="$LINKFLAGS -Lx:/libs/dir -lmylib" -largeArrayDims file.cpp
A- @9 S0 p9 P0 h
3 \9 d [( v5 h g3 W) b5 A, |" B# D% o. O4 {3 z+ ^% {
选择编译器
; E; o2 G! w( t* @( _9 f# _- 查看可用编译器:使用mex -setup查看可选择的编译器,如果没有需要自己安装,如果已安装且只安装了编译器Microsoft Windows SDK 7.1(C/C++),显示如下结果:8 Y8 e7 v9 J( E: T: b0 {
- 选择编译器:使用mex -setup lang选择编译器,如mex -setup C++选择C++编译器,如下图: 8 |% S; G2 d; j Q, q; H
- 如果你也按上面TDM-GCC(gcc/g++) 中讲的方法,配置了TDM-GCC-64位的编译器,那么,你会发现结果如下: \) L3 s; Z9 k' L5 r, G0 Z
& o$ K2 A* {& h( Q( x! o
1 p; h- ~! e$ S& X1 k
4 u4 [+ V/ \. @' Y& U# g刚开始我也以为不能用,后来试着编译了一下,竟然可以! 4 K4 p% k f5 U3 [5 v/ D$ I
) m- Y7 w) w: o" B% s
DT.c文件中重复定义了无穷大,注释掉,就没有提示啦!
" P, Z, n6 [, t' o1 [- G# R
& E) |$ |: l5 l
$ u4 A, r! \! d Y7 N8 k编写c/cpp文件
" }' i* H8 W5 ]6 @3 Q与普通的C文件的编写有两点不同:
: {; P5 @& o7 Y a5 H: _" M# b+ P# _7 Y3 ]5 x
- 包含mex.h头文件,即:#include "mex.h";
- 编写mexFunction函数。" W/ c+ A( r1 g& V2 s
! h) R/ w* x+ {6 L( c% k- J7 |% U
/ M$ j- _% o& \" h2 ?, `5 M" n下面以一个求和的例子说明:$ y; e, q3 N' X+ ?' T
+ k" `3 e4 H. ?. v" g+ s+ ?1 _
#include "mex.h" // 使用MEX文件必须包含的头文件9 u8 v9 J& X" Z/ D6 I4 s3 |
// 执行具体工作的C函数
9 @' M6 Z( K) k: j6 q0 ]2 W, zdouble add(double x, double y); A4 T Z6 ~ y/ j4 C4 c5 H# o! @
{
0 V" l% j8 o* d9 R- h4 T" X% g return x + y;" s$ |" l: g7 i0 w$ x! Y
}
% x* V" U# x* N9 F// MEX文件接口函数& V; Q" H# X& l/ J# {( @
void mexFunction(int nlhs,mxArray *plhs[], int nrhs,const mxArray *prhs[])1 {6 }) [( R; B* B6 v7 W
{
) f& r# A) b- L2 M: U double *z;
- Y4 `) H! C0 c double x, y;
: B# a( x" f) ]$ c+ m plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);) I9 V! d7 @# V& X; G, Z
z = mxGetPr(plhs[0]);
' ~; d, ^- P& H1 W1 \* w2 c x = *(mxGetPr(prhs[0]));! s8 P( V# }% L7 I" e
y = *(mxGetPr(prhs[1]));
b0 E) n% l& {* q8 t/ R *z = add(x, y);
?0 T% t! A/ K}
- f+ o8 S* a9 d3 l Z7 t' y' j7 I3 p6 o7 g( E6 _: h% C! E
3 s$ R) `" ]8 e2 N8 f9 _ oMatlab命令窗口输入mex add.cpp,运行结果如下图:
+ P- ~: b1 |8 L, u b- \
0 q7 l6 j+ ^( o: C7 j
: I& u$ ]4 {0 o: C( L$ s# V/ D
在Windows上编译后生成mexw32和mexw64文件,在Linux上编译会生成mexa32和mexa64文件。
; B! o2 l+ \4 T; o0 ^& w% V! t/ e" {8 H$ Y% R/ y4 N" }! D' _
mexFunction函数介绍, H3 g( v4 ]' q
mexFunction函数接口如下:+ ]1 h" W) X) x z, N$ x; Y6 ]
c9 \7 D/ ]8 J% ?) g6 ^
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
: j' C% r/ P E% Y
8 }8 v0 ]% c( }2 _- C可见,是没有返回值的,其实是通过指针数组plhs传递的。它共有四个参数,即左边的输出参数及数目和右边的输入参数及数目,具体参数意义如下:8 }) a, S1 c1 p9 l1 l2 _4 {
; w; ?" D$ N W6 u( _
参数 意义 英文全称 类型2 @( S6 ~ A8 R6 L+ g5 Q
nlhs 左边输出参数的数目 number of left-hand side 整型(int)! }8 Q" l0 ^+ `- ^
plhs 指向输出参数的指针 pointer of left-hand side 指针数组
( ]1 ~3 y5 s: A$ R) R! ]; J* [nrhs 右边输入参数的数目 number of right-hand side 整型(int); ^) ^' w& T( G0 F- }/ H; P4 r2 c0 }
prhs 指向输入参数的指针 pointer of right-hand side 指针数组6 O) g) {. l: y, i5 a" O% Y
5 N$ I" [2 a' n详情参考:
7 Q$ `8 s' W5 J' _. g- w/ q# o: \7 S' f+ [3 l
- Matlab参考-MEX库
- MATLAB中mexFunction函数的接口规范(转载)
- Matlab与C语言程序的应用编程接口
- matlab和C/C++混合编程–Mex
b- P4 w1 |, ]) L % T: t# n* L1 r. U/ ]6 K# z
8 {6 r; E/ t) ^编译多个c/cpp文件! j7 l# O1 G, h
假设A.c调用B.c,B.c调用C.c + e: f, ^- @. }0 z! K
可以使用如下命令编译:; Z9 ~& S- Q" ` N
6 X: d3 X# x: q( w
mex C.c
* `. Q e. U- ?# _mex B.c
2 ^2 C6 m5 ?3 p" C1 W2 dmex A.c4 l/ I K% z2 ]. X* G: Z: P: }
- L: j2 {: E. _" @- \5 n2 O3 q或者
# ~% H' x+ E+ g0 k+ p) I$ O
$ x) {. z" t+ A2 E( ^mex A.c B.c C.c
& ^" p5 ~! K; j- e$ b3 J0 Q5 }5 Y
7 U# b% r2 o1 ^
4 `7 }8 p( p% i. n
! C6 h( C! E6 ?7 [) U) w5 W( c/ }- [5 F- W, m
- V, W; c4 W4 K, R4 z3 F6 t
|
|