|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
说明: N* O' J% Z+ r2 C9 F/ N
Matlab混合编程
/ C. o4 X/ Z4 W" a6 C& H 下载与安装编译器8 _3 ]2 g" R4 Z4 }& x7 G* p( ~
Microsoft Windows SDK 71CC
- g" U- B( U# L' U TDM-GCCgccg
6 S5 N+ D4 C: p! J* H0 b8 o For Matlab 2015
! e! l4 G3 r& Z* x$ A5 Y For Matlab 2014: g% n' I# l" w
选择编译器
8 x/ |2 v6 `2 k; Q+ ]& B 编写ccpp文件) z7 B, w' B: A5 N- N2 I
mexFunction函数介绍) {% W! J; ]5 L; A" ]
编译多个ccpp文件$ x- |" c+ ^& j2 M8 o) N3 t* p) F
* @( o# \# y! f- p# n
; E4 ?1 x2 p# S. n w7 e说明, h2 S1 R7 n- v7 [2 y. x
记录本人在Windows下,使用Matlab 64-bit 版进行混合编程时遇到的问题,主要记录编译器的安装与简要的混编过程。
. w* [3 g6 E! D. Y* d9 f j' ^1 r5 E" [+ J4 d3 {! P0 O
- 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)' B$ l5 c8 {" w @8 |; n
% h" V9 W* E5 G& \/ ^
/ P! h8 h. ^ _3 D k4 x- k6 M' J5 p; \" W j7 O
Matlab混合编程
, S1 b" U! } H& _8 V) O下载与安装编译器
+ E* ~+ H# c2 N: `6 xMicrosoft Windows SDK 7.1(C/C++)5 G5 V- Z' C: J8 E5 i% G
点此Microsoft Windows SDK for Windows 7 and .NET Framework 4 (ISO)打开下载页面,是镜像文件,选择64-bit版,文件大小500M+,全部安装需占磁盘近2G。
2 c, F" M* m& }( U! z9 T
: E' e$ D3 B3 {) ?8 i& o下载完成后根据提示安装即可,如果出现问题,安装失败,参考:Problem&Solution 部分。
% z& Y q }) k3 _3 m! x. g
8 L; y8 e. n7 i* {9 b7 s7 GTDM-GCC(gcc/g++)
7 w& z& c' p1 ]2 W# cFor Matlab 2015
! r: W5 _/ q7 b9 I" c. LMatlab 2015已经开始支持GNU编译器,具体参见:Supported and Compatible Compilers for R2015b,安装方法参见:Install MinGW-w64 Compiler。
0 i+ b7 ~9 `# \) }4 T
- q. Y* V% y/ X- x; f- 注意,MATLAB 2015现仅支持GCC4.9.2,在安装TMD-GCC时,不要勾选更新,如下图:
4 H3 y. r1 W$ \+ P* z% n5 T , a( \) n4 e% U# O' y% e
3 j- ^& x* y: X8 J5 \( G8 f
+ g4 O+ y6 g/ U! h3 O- 然后,还需注意的是安装路径不能有空格;
- 需要添加系统环境变量MW_MINGW64_LOC=your tdm-gcc path。
- 重启系统和MATLAB后,输入mex -setup显示:& d6 U( Q; a, w: P. k
4 X5 v3 O) _0 p/ T) v+ _
* a' D& g% w/ q* {$ z' o
# C& T3 I8 ?( n$ b! _% A
至此完成!8 T8 P3 ^+ h! r( Z( q5 c$ d! G& k1 T
2 c, j! P: Z5 |+ _
For Matlab 20143 J1 e. q! }% j5 K+ j
如下文章针对于MATLAB 2014a。
& q3 K8 O9 y$ z: N- ~6 f1 _* f9 Z. V, ^3 l- X3 n
点此tmd-gcc打开下载页面,选择64位版本,40M+,全部安装占用400M+磁盘空间。
6 a( T8 T9 C- t |1 u
- J% v9 w9 k( ~) m& U; f根据以前使用经验,安装路径最好不要有空格中文。
, W( a7 V5 J3 q8 I6 W
/ B9 c( l% N8 a4 G* P M安装完成后,开始 -> 运行 -> cmd打开Windows命令窗口,输入gcc -v,如下图所示,显示安装信息,说明安装成功: ( V8 \% o+ L' _
$ W# o2 j& m# V2 N
- R1 U* Q, R' h) X: ]最后的战斗: / J( z7 _0 I' }( L" l: N
因为Matlab不支持GNU的编译器,还得做点事,下面的方法来自Using GCC (MinGW) as MATLAB’s MEX compiler 中的Bogdan的解答:4 A: z2 Z( r) Z- j- U
! i& K# o! }- ~, c1 [$ ?) M下面的代码是从Bogdan主页上下载的mexopts.bat文件代码,使用时需要做一点小小的改动。
0 g- U: a; @* T7 f; h9 K g. |
/ [" H- A/ {! o9 [, g在下面的代码中找到:set MINGWPATH=p:\mingw64这句代码,将其中的路径p:\mingw64替换成你的TMD-GCC-64的安装目录,如我的是:E:\devtools\TDM-GCC-64,然后保存并将mexopts.bat文件copy到计算机如下路径(复制下面的路径地址,粘贴到资源管理器窗口地址栏,回车即可):3 @( d6 A; |7 A4 q
u" q! i( u3 F. ?0 \. ~9 _* D
%USERPROFILE%\AppData\Roaming\Mathworks\MATLAB\R2014a\
, T" Q1 k" Z) d! x$ c# B# F% \. e, T. Q
下面是代码:
% R$ l! Y7 R, O! G1 E, x$ d" u! H. U0 M2 F2 F
@Echo off9 K/ v5 w/ P3 R1 L9 s- |% `
5 v8 I) |8 ~0 Z8 ~3 J:: NOTE: this is actually not a proper .bat file executed by Windows. MEX
. Z- [9 @0 x1 P: ^& @ j:: parses it and only understands a very reduced set of commands:
( G9 s% {) ^) n2 ~& s9 D:: "set" and "rem" apparently, everything else is ignored (behaves as
4 [- Z$ U& }: c. W5 q! h7 z:: "rem"), so don't do any fancy batch stuff in here. There are some+ z, s% L' p( s! P
:: undocumented special vars you can set here that will trigger MEX7 h: t' \# n6 z) @- P+ m* @1 B6 ]3 V
:: to do fancy stuff.
7 P1 \) O& U% B! j0 _$ h
% k6 J0 V( I0 B+ [3 c, y; @- t) E:: You can use MinGW64 builds (win32 threads + seh unwinding) from here:
& _# }9 N9 [0 d* L0 j4 b# o:: http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Personal%20Builds/mingw-builds/
9 J7 S* T' y: g0 M- k V3 `
' f7 k! K# T9 z" X:: Tested with the following:4 y" g% \ _0 |( I
:: 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.7z7 |) p. D8 `- i! ~
7 ?6 T* M6 h" K5 z$ s& y, E8 G:: Set this to your Mingw64 top folder, where you extracted the above
6 H- B% c2 V* Z) n/ M; g+ Dset MINGWPATH=p:\mingw64 E. {/ P- b _: e! [8 g
. p4 B9 I/ ?9 I. C:: Leave these alone unless you know what you're doing.$ q5 Y( I* E. ?& ]
set PATH=%MINGWPATH%\bin;%PATH%1 `& ]2 @6 }6 X( _8 w
set PRELINK_CMDS=echo.>%TEMP%\mexstaticlibs3 K* _; _' o7 c1 S
4 S! F: N' D, T0 l( T; g
:: You can have MEX run some commands before calling the linker.
- g3 h4 c' t; ~7 x: K:: The two examples below will cause gcc to output the full path to some) a( c& z$ V6 l) f. W/ a
:: static libraries so you can link statically to them (see the
[ V2 R( K( ]% `:: LINGFLAGSPOST special var below). You can set any command here, however.- b% G# N) k( A d
rem set PRELINK_CMDS1=gcc -print-file-name=libwinpthread.a >> %TEMP%\mexstaticlibs
8 m5 S7 n3 B M9 x7 Q+ prem set PRELINK_CMDS2=gcc -print-file-name=libquadmath.a >> %TEMP%\mexstaticlibs
# N9 c" K1 E# b/ Q- U7 urem set PRELINK_CMDS3=...
) ]9 J5 ?. T9 {! V7 E- {" _! W4 t4 y: y; M* c0 }) [
:: You can have MEX run some commands also after calling the linker W5 m+ W& x1 ~$ b: w
:: (e.g. upx compress the output .mex)1 y6 y L4 g, M) ?
rem set POSTLINK_CMDS1=upx -9 "%OUTDIR%%MEX_NAME%%MEX_EXT%"+ Q8 @& F* x& a1 _
rem set POSTLINK_CMDS2=...
- I- Z. i' G7 G4 q) j) n2 O# {- m
' U/ H3 @3 ~+ u4 F* d:: You can change these if you really need to.
" ]8 r: ^2 g+ \4 X5 _( |! `set COMPILER=g++
3 z9 D R$ O' a1 ~+ gset COMPFLAGS=-c -I"%MATLAB%\extern\include" -DMATLAB_MEX_FILE8 ~. ~9 `3 n. p0 m
set OPTIMFLAGS=-O3 -funroll-loops -DNDEBUG! C- H8 [2 m3 f( n) G% Z
set DEBUGFLAGS=-g
/ ~' G2 U! L! r5 S5 J: i2 Sset NAME_OBJECT=-o& ]" `" y. r4 T/ V2 Z8 {
% s H1 G z7 K" V/ X, O5 Yset LINKER=g++
4 j5 D8 P: e2 @% G2 oset LINKFLAGS=-shared -static-libstdc++ -static-libgcc -L"%MATLAB%\bin\win64" -L"%MATLAB%\extern\lib\win64\microsoft" -lmex -lmx -leng -lmat -lmwlapack -lmwblas
( q) x3 K- p- ~
- ^0 N+ I' H! T `set LINKFLAGSPOST=@%TEMP%\mexstaticlibs
* C% P( _! N! P3 G. ]. e% k4 Fset NAME_OUTPUT=-o "%OUTDIR%%MEX_NAME%%MEX_EXT%"" G+ Q1 M) `# y
! e" @, s8 n3 @) A
- T2 n3 o/ s& v5 q% c:: EXAMPLES6 s2 ^# L* o0 k/ n5 k/ u% H
:: ========8 `. L4 r9 f3 l' M k
& w6 E7 B3 T, O* U T: M2 f+ \; D, u:: You can compile simple files using "mex file.cpp". To support more than 2^32 elements, use: L, |2 Z5 U& J& C
:: "mex -largeArrayDims file.cpp" ... use this by default, unless you know what you're doing.
! J6 s3 G- ^, e8 q7 o$ X1 b& I- A- f9 ]4 k+ @
:: To add include dirs, lib dirs, or compile/link flags, do:
" l: S8 N5 R- d' L! U$ \: Y) Q3 B:: mex COMPFLAGS="$COMPFLAGS -std=gnu99 -Ix:/include/dir" LINKFLAGS="$LINKFLAGS -Lx:/libs/dir -lmylib" -largeArrayDims file.cpp8 [2 l4 ^* u& A7 D0 F: ~
B' ^$ H$ r$ {+ f! i8 Z! B) k+ D- A
( n3 P! ^, K8 X9 u选择编译器
2 r Z1 M0 f9 c! n" t# q5 Q" K- 查看可用编译器:使用mex -setup查看可选择的编译器,如果没有需要自己安装,如果已安装且只安装了编译器Microsoft Windows SDK 7.1(C/C++),显示如下结果:2 G4 S6 ^$ z9 c" p1 B) V
- 选择编译器:使用mex -setup lang选择编译器,如mex -setup C++选择C++编译器,如下图: 0 E8 x5 z% U" m/ B0 _$ S2 F: x
- 如果你也按上面TDM-GCC(gcc/g++) 中讲的方法,配置了TDM-GCC-64位的编译器,那么,你会发现结果如下:
; \& ^" t6 c3 ], ^4 G
, _3 K4 n' F. S+ r# W
& c# c- D( z9 r2 Y2 h+ |2 l3 A9 V" }% Z6 T5 F7 O: y
刚开始我也以为不能用,后来试着编译了一下,竟然可以!
7 y$ J' Y! f& E; u g( R
% k, l8 e9 e9 {. ]: IDT.c文件中重复定义了无穷大,注释掉,就没有提示啦!$ J3 o& ? _7 x+ m
" X" n$ K9 H1 V0 a( H! Y: M/ ?) O+ X( @! K
编写c/cpp文件
, n V& m* m1 v- T5 j; n与普通的C文件的编写有两点不同:9 r ]4 I0 E! A. @! ?7 g
% t8 ]' e3 u' ]4 ?- w2 S. G
- 包含mex.h头文件,即:#include "mex.h";
- 编写mexFunction函数。
0 c* f* {/ d4 t- [4 A
6 h3 T3 Q0 s% }8 l" S$ u
) {9 o" Y4 l8 l/ `% I! P8 i下面以一个求和的例子说明:
& L6 A+ p5 k) p3 [! ?# J& h+ r; X$ \; z. g
#include "mex.h" // 使用MEX文件必须包含的头文件* G. r- _( e/ j
// 执行具体工作的C函数
' H4 q6 S8 B! tdouble add(double x, double y)1 W* D! V' n$ L# v
{
5 l: c: o/ L( G% X. k3 u* E return x + y;
) {; P) b3 ^& C0 K4 C7 B: e}# l& [/ d7 S2 D2 U3 [6 [, w
// MEX文件接口函数
& h4 A7 H X4 O# `8 n( }( Rvoid mexFunction(int nlhs,mxArray *plhs[], int nrhs,const mxArray *prhs[])
7 [! C, {# Z$ O1 R. ^% K; P- F{) ~1 w$ [8 V" D
double *z;% p. Y1 G! G4 s* p6 P
double x, y;
$ o4 M8 j. `% z! x: S plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);* C# g9 R& c( j# o
z = mxGetPr(plhs[0]);- ]9 T9 R4 K3 M: N
x = *(mxGetPr(prhs[0]));
: y! R, O9 x+ q) Q1 u n y = *(mxGetPr(prhs[1]));; h! ]; o! u7 L; ~" z0 u+ B5 p
*z = add(x, y);
; Z9 h7 v% k7 o) ]% m: J. M2 o8 r}4 ^1 C/ X; _5 Z
6 I, g, M3 V- w1 c. o6 }, ^# a3 v* f" \- x( s) f1 V
Matlab命令窗口输入mex add.cpp,运行结果如下图:
: I6 Q6 z- ^0 m+ E/ {
9 y. q7 ]) M8 f a ~$ w$ D% Q! x" Y# g% b$ C
在Windows上编译后生成mexw32和mexw64文件,在Linux上编译会生成mexa32和mexa64文件。
9 F0 J) T- j/ W* F( U# b1 `0 Y. h+ D( I1 r; \9 a
mexFunction函数介绍2 J4 ?' i. e" o" _
mexFunction函数接口如下:4 }# n) a# ?0 i8 ?$ @! [5 |8 b
" Z' c$ U! ]; j: c4 l' ivoid mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
# Y% {4 O) ^+ z& ? b, T* u }% g, n$ l% j, `) [& M/ L
可见,是没有返回值的,其实是通过指针数组plhs传递的。它共有四个参数,即左边的输出参数及数目和右边的输入参数及数目,具体参数意义如下:
\ i) l% a* C3 `* C$ ]
, B ?* `" G' e. o' A参数 意义 英文全称 类型* U; B/ V6 l; d/ V+ A7 x2 I: e% j
nlhs 左边输出参数的数目 number of left-hand side 整型(int)
. R- V' _: S+ nplhs 指向输出参数的指针 pointer of left-hand side 指针数组$ A {, w4 w3 h# G* j# y
nrhs 右边输入参数的数目 number of right-hand side 整型(int)
X5 ]) t6 h: O- Fprhs 指向输入参数的指针 pointer of right-hand side 指针数组- u; D: `) [9 l; g& W
5 a5 X8 e) L: C' _详情参考:
- n" [1 ^2 _. \* ?
8 \- G5 c Y+ j! `9 L5 H- Matlab参考-MEX库
- MATLAB中mexFunction函数的接口规范(转载)
- Matlab与C语言程序的应用编程接口
- matlab和C/C++混合编程–Mex8 P D- i& X& E0 t! X
2 m+ O* x8 ?5 Y% J% k/ M! h- A+ t# X
7 J4 f1 H) J3 _
编译多个c/cpp文件
: g- o+ _, ]3 f- ]: U假设A.c调用B.c,B.c调用C.c 9 ]6 L! P, m0 o& N
可以使用如下命令编译:
6 x' c8 z: j* I4 k) b% t( C" m6 N6 P, E T* x" B% R/ a: V- S3 n" ]
mex C.c
H* i5 {- G2 P1 Pmex B.c) e, `- D9 t- B* J6 x+ J1 }) ]3 y! K
mex A.c" E5 W5 k+ v: a3 [& `' T
! `# r: h+ @' m
或者
+ h n0 d/ j. T4 F' a5 i; O& n8 x3 b& F: z! ^8 L* `! m
mex A.c B.c C.c% ?: N8 ~$ h0 c- x& U, ?
% I2 T& s; ?% ]% O5 k3 X
0 _# ^ x. E; c1 j) m
; [$ m' _0 a- `7 s3 k
' T) o: d+ c4 }6 x
" @- {% N( I; @2 h+ w- f7 P+ }
* \; V9 i& X/ G |
|