|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
说明
! ~: t" N4 p" N" \/ G a* p9 [Matlab混合编程3 \! I$ o6 |2 B2 u3 P0 Q" s
下载与安装编译器
0 z3 t3 ]0 f4 k" S Microsoft Windows SDK 71CC
. [4 X+ W& R ~7 z, F/ W( g TDM-GCCgccg1 u `% t" G3 s
For Matlab 2015( x1 D8 a6 R- T$ Y" U
For Matlab 2014
* {7 K, t+ t7 L5 M q 选择编译器
& O* I" m9 p& J9 c" w! s/ S2 c6 B; k/ L 编写ccpp文件
8 c; r0 |- M1 Z5 v4 ^ mexFunction函数介绍
/ \7 g$ ]- _& M$ r 编译多个ccpp文件
. R" S# i5 K+ r9 I9 I: Y5 g1 @# z( g
. }; `( k" q* G7 j- }1 W说明
, R4 Z+ |6 D/ R% R2 D记录本人在Windows下,使用Matlab 64-bit 版进行混合编程时遇到的问题,主要记录编译器的安装与简要的混编过程。
! w8 r2 M$ A* w8 ]' L6 ^; A& |9 J7 ^4 S9 H+ H4 E4 R
- 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)
# V1 u9 n+ x' ^) j" y {
( B `+ z1 A8 \: U4 n g: u
" a' P! q1 `* x' L% x2 m: A$ @2 L' F( f& `
Matlab混合编程6 V! }# Y! Q0 g4 J" x: T2 G- |* |
下载与安装编译器
8 n! ?) G0 Z% a8 ]Microsoft Windows SDK 7.1(C/C++)
) A+ ]5 A- h k* N, O& G点此Microsoft Windows SDK for Windows 7 and .NET Framework 4 (ISO)打开下载页面,是镜像文件,选择64-bit版,文件大小500M+,全部安装需占磁盘近2G。
/ ^+ j7 h L/ _+ x0 _
* H* a9 E0 j' g) H( n& I: j下载完成后根据提示安装即可,如果出现问题,安装失败,参考:Problem&Solution 部分。* i( m+ f5 `0 E; c; i$ M* h% [! ?" l! u
1 j M* ?9 @# F b8 BTDM-GCC(gcc/g++)6 d) [: c( T0 y" B; l
For Matlab 2015
2 F; y( S: ?$ f' O" V( ?" aMatlab 2015已经开始支持GNU编译器,具体参见:Supported and Compatible Compilers for R2015b,安装方法参见:Install MinGW-w64 Compiler。3 [0 u" k, q! ~5 P! O
( G$ E/ [& r S- }: B- 注意,MATLAB 2015现仅支持GCC4.9.2,在安装TMD-GCC时,不要勾选更新,如下图:
) }. A5 F `5 H' O* |# H - Q+ d, H1 d Q+ S* J
0 X2 j9 f% l! \$ v, ~
; _9 @- z: {; Z& v- 然后,还需注意的是安装路径不能有空格;
- 需要添加系统环境变量MW_MINGW64_LOC=your tdm-gcc path。
- 重启系统和MATLAB后,输入mex -setup显示:
6 z" o3 g6 B3 ]5 B- g# ~ . V( N1 j5 P k: n/ V$ i" h0 f
, t& P3 i: I5 d: j
$ Q7 {9 d4 s) S% O/ w4 m
至此完成!
) i9 z3 Y8 x( N: m% h$ c3 f$ c# ~1 ^ G H+ D2 F& {
For Matlab 2014. p: K0 ?: w' Q& l: ?7 i: a
如下文章针对于MATLAB 2014a。
F9 M# _, ]7 D" v+ l* d" K* }7 R/ `2 a+ F. j' P$ [
点此tmd-gcc打开下载页面,选择64位版本,40M+,全部安装占用400M+磁盘空间。2 b" o4 C' U" X' @1 `
$ }( w4 M* B( R/ g( q+ y8 z根据以前使用经验,安装路径最好不要有空格中文。0 c2 u# }" Y+ O& \0 ?& X. E
0 z$ c# @1 S% \+ M Z' r
安装完成后,开始 -> 运行 -> cmd打开Windows命令窗口,输入gcc -v,如下图所示,显示安装信息,说明安装成功: 0 J& }3 ^2 C+ k5 e8 b
, A+ a! F. t. a- M
! r/ G$ H2 C( ~3 V最后的战斗: 8 Q$ c) ?* r9 j$ q2 v" a
因为Matlab不支持GNU的编译器,还得做点事,下面的方法来自Using GCC (MinGW) as MATLAB’s MEX compiler 中的Bogdan的解答:- A0 W6 D& b- b
( D$ x, a5 |: n6 b
下面的代码是从Bogdan主页上下载的mexopts.bat文件代码,使用时需要做一点小小的改动。
- n3 Y) ]$ m% u7 `' _1 g+ g8 E& u
, k0 ~! \& B- e E, C: K" c' R2 `在下面的代码中找到:set MINGWPATH=p:\mingw64这句代码,将其中的路径p:\mingw64替换成你的TMD-GCC-64的安装目录,如我的是:E:\devtools\TDM-GCC-64,然后保存并将mexopts.bat文件copy到计算机如下路径(复制下面的路径地址,粘贴到资源管理器窗口地址栏,回车即可):4 B$ Q* F8 B. k# F
: e5 G1 o' @' |
%USERPROFILE%\AppData\Roaming\Mathworks\MATLAB\R2014a\
7 f7 j1 J& `9 b/ N; f) P
. C: n1 @+ P: j" Y& n下面是代码:5 J1 i5 V, z* v0 m# w6 @
3 l' ^, @ H2 u6 S1 @' _
@Echo off
; H- L; |3 D4 b( O. D( a/ e; M
& w9 x4 p2 Z, K+ f+ T( ^. f:: NOTE: this is actually not a proper .bat file executed by Windows. MEX
: k) ^/ x+ h7 | T* |:: parses it and only understands a very reduced set of commands:, U4 C5 N6 k7 x( I% ?' i
:: "set" and "rem" apparently, everything else is ignored (behaves as1 j% I! P" Y' P; ?' G9 W# ~
:: "rem"), so don't do any fancy batch stuff in here. There are some
2 o* ]5 e+ }4 W5 g6 r:: undocumented special vars you can set here that will trigger MEX
8 ~: [! G* `$ i& g$ ]% a8 l9 N:: to do fancy stuff.. s- Y3 [9 u w" [
7 V9 {$ X* ?" |# i- E
:: You can use MinGW64 builds (win32 threads + seh unwinding) from here:
' E, h5 L0 |# l* u, y; W" z:: http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Personal%20Builds/mingw-builds/
7 x7 w. ~8 a+ m/ _& {' ]1 U0 I: b
:: Tested with the following:; ?7 J' K3 ~0 I" u! h% T
:: 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
% e5 |4 Y- S0 x* j; [( S( G% w& ]+ m7 K6 T+ [8 w9 f) h, `
:: Set this to your Mingw64 top folder, where you extracted the above# B' h5 r& y5 A @5 p' T/ a9 f
set MINGWPATH=p:\mingw64
& D4 s3 P7 n' M% \6 ?: o
3 u. T7 e. C6 p( L% O. M* d4 r:: Leave these alone unless you know what you're doing.
3 ?2 }5 w5 ?5 }4 @3 L- kset PATH=%MINGWPATH%\bin;%PATH%
+ _/ x6 u( u$ l- a9 G8 \. ^. @set PRELINK_CMDS=echo.>%TEMP%\mexstaticlibs
& ~% i( n: e% k9 X% X! ?+ o
5 P( g1 c# P' j: i: y5 n:: You can have MEX run some commands before calling the linker.
3 Y' V7 l6 V. R/ C7 x! P2 D:: The two examples below will cause gcc to output the full path to some9 r8 b$ I! E* F3 i* n E. H
:: static libraries so you can link statically to them (see the
1 q/ S" a/ i m- H4 K. k; W:: LINGFLAGSPOST special var below). You can set any command here, however., @4 z# w$ o9 L! \. W
rem set PRELINK_CMDS1=gcc -print-file-name=libwinpthread.a >> %TEMP%\mexstaticlibs
! {- b" g% X& O0 y9 i, M2 irem set PRELINK_CMDS2=gcc -print-file-name=libquadmath.a >> %TEMP%\mexstaticlibs
' w0 h; V- s$ \: z5 Jrem set PRELINK_CMDS3=...# b) d1 G9 v3 k7 D4 H! X
3 i. S, m2 ~3 r2 ?% P% [:: You can have MEX run some commands also after calling the linker: A: f# V0 Z" I3 U" N
:: (e.g. upx compress the output .mex)
3 `, z( L- c n# }2 |rem set POSTLINK_CMDS1=upx -9 "%OUTDIR%%MEX_NAME%%MEX_EXT%"7 l) p) o; f2 t$ u0 ?5 L
rem set POSTLINK_CMDS2=..." B1 P, G& w4 L, w Y# v4 E
; Q% a* S$ r0 A
:: You can change these if you really need to.' ^: P% W( p5 v2 U1 g+ G
set COMPILER=g++# [6 d1 \2 G: `7 h$ B& g4 k
set COMPFLAGS=-c -I"%MATLAB%\extern\include" -DMATLAB_MEX_FILE, U& J, p- B$ b- [ k6 J8 ?3 x
set OPTIMFLAGS=-O3 -funroll-loops -DNDEBUG) J+ }, L" H, t7 c9 ]
set DEBUGFLAGS=-g! p9 M" r5 f6 W' ]3 L
set NAME_OBJECT=-o5 K4 n3 v, D5 R' o, ]! O. C
( O* m7 B6 r8 j0 V" K! M! Q3 a8 Zset LINKER=g++8 W/ U$ R; V- ]1 X! q4 I
set LINKFLAGS=-shared -static-libstdc++ -static-libgcc -L"%MATLAB%\bin\win64" -L"%MATLAB%\extern\lib\win64\microsoft" -lmex -lmx -leng -lmat -lmwlapack -lmwblas
( l1 b4 q. M; e1 A
3 x, z, t3 s9 S- vset LINKFLAGSPOST=@%TEMP%\mexstaticlibs$ V9 z. h$ D: d. D4 k) y
set NAME_OUTPUT=-o "%OUTDIR%%MEX_NAME%%MEX_EXT%"3 F( L$ |! w+ z6 Z. `# _$ ]7 m
$ u5 l) O4 y! @ v
+ I6 Y9 U0 p0 O4 j7 O( a$ Q! U:: EXAMPLES
+ {2 X( _. ^: {1 ` o# L:: ========4 q' u. n0 ] p2 l ]3 j
# J5 h1 F: z# W2 ~
:: You can compile simple files using "mex file.cpp". To support more than 2^32 elements, use- v9 x0 d0 z4 U
:: "mex -largeArrayDims file.cpp" ... use this by default, unless you know what you're doing.
+ B) x3 O9 t* m9 J* n A" V5 D" F- E* J9 B0 {8 x
:: To add include dirs, lib dirs, or compile/link flags, do:
9 L' |6 G' X# r:: mex COMPFLAGS="$COMPFLAGS -std=gnu99 -Ix:/include/dir" LINKFLAGS="$LINKFLAGS -Lx:/libs/dir -lmylib" -largeArrayDims file.cpp6 B- o0 I! L! Q- ` T4 v
/ J! h* X( F! D+ X2 K2 T, ^" }% _1 F& Z% E
选择编译器: N7 {( p% b4 T( X
- 查看可用编译器:使用mex -setup查看可选择的编译器,如果没有需要自己安装,如果已安装且只安装了编译器Microsoft Windows SDK 7.1(C/C++),显示如下结果:0 B& B7 A' ]% {% ^: C2 C
- 选择编译器:使用mex -setup lang选择编译器,如mex -setup C++选择C++编译器,如下图: 9 c% ^# s0 @: g/ |5 `* I# @9 @
- 如果你也按上面TDM-GCC(gcc/g++) 中讲的方法,配置了TDM-GCC-64位的编译器,那么,你会发现结果如下: / Q' z6 M% ?7 ~
" D, V7 [7 S6 B( w
$ f% }, i: e% ^# v- j
; J. f+ ~6 f) e7 Q% c刚开始我也以为不能用,后来试着编译了一下,竟然可以! & u9 O5 l" I4 l7 d4 X* q& s/ \, V( t
. Q( I% p! D/ {, X% l
DT.c文件中重复定义了无穷大,注释掉,就没有提示啦!9 W9 @' w/ W( r0 _' c6 D
/ `# ?6 Z2 _. A3 v- O' }; ^0 ?2 f& N% _1 s
编写c/cpp文件
5 j1 M4 t5 F# @! ?与普通的C文件的编写有两点不同:
3 e1 j) d4 ~* p! h, d7 `8 J/ [: m3 J8 J9 J7 ]
- 包含mex.h头文件,即:#include "mex.h";
- 编写mexFunction函数。
$ t" l9 r0 m) E0 {7 @, | + @6 {; t J: \7 [2 B- I
8 E4 V7 C# [! v/ H- v下面以一个求和的例子说明:
1 i! |4 H2 ~1 I" b1 I8 ^" w% v% t# b
#include "mex.h" // 使用MEX文件必须包含的头文件( n: S# J- I' X( Y7 m, R
// 执行具体工作的C函数
! U2 e6 p5 V7 n, Z2 N. J4 tdouble add(double x, double y)4 a0 F, I! ^# q o) D4 X* Z& d' O
{
7 A, L! i# y) v8 r return x + y;
0 b- H! B! [2 N, v0 Q& ?" A& J}% C" p1 S& h, ^% Q5 J
// MEX文件接口函数" P4 V' L, _+ ~9 s& y' X' ~
void mexFunction(int nlhs,mxArray *plhs[], int nrhs,const mxArray *prhs[])5 C1 W* K# K3 U, h/ u" E# R
{
% M. e( J# b$ `2 ` double *z;
7 S: d& l, S$ K& C4 F. O; y double x, y;/ ~" Z4 n" ?; y3 {( V; i
plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);8 q' P" A( U* ^# \) R
z = mxGetPr(plhs[0]);
' c7 d: F t5 c! B! ] x = *(mxGetPr(prhs[0]));
) j, g. [& Q' D8 }7 Y* Q& r y = *(mxGetPr(prhs[1]));
+ k2 j2 f2 o5 V7 V3 e- ]) P *z = add(x, y);
1 l( C: Z: \, Q3 c( S/ r}& f# v: T& h$ f8 H7 j; K9 r
q, C% I2 F3 G2 I0 G
. B) J+ @/ w* Z4 c0 I
Matlab命令窗口输入mex add.cpp,运行结果如下图:
9 i3 f) W$ T9 K/ g5 {* W& \: k
* e" s# d' p; S; u9 [9 {+ {2 ~" f2 _0 B5 w( }
在Windows上编译后生成mexw32和mexw64文件,在Linux上编译会生成mexa32和mexa64文件。; ?3 O6 C$ Z0 ~0 U9 W( _4 r! S
3 Y1 a8 M. b4 e; T! GmexFunction函数介绍3 A! y4 N) F% e6 ]$ Q
mexFunction函数接口如下:+ {8 Z A) V7 S& T1 `
* P/ E9 N& j7 svoid mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])" J5 `# }" T Z- ], i' p
" j8 v* z! @5 V2 h7 C* b
可见,是没有返回值的,其实是通过指针数组plhs传递的。它共有四个参数,即左边的输出参数及数目和右边的输入参数及数目,具体参数意义如下:- E1 S, d C! W( v' u! x) Z
( I: N2 p- e& A3 N% Z- I参数 意义 英文全称 类型
& j! }+ K4 ^1 F+ j' Y% k7 @nlhs 左边输出参数的数目 number of left-hand side 整型(int): l: c' p) h8 H" |+ V. ]3 N
plhs 指向输出参数的指针 pointer of left-hand side 指针数组
9 L! ?) S( K4 R& I6 C7 a6 xnrhs 右边输入参数的数目 number of right-hand side 整型(int)0 B/ G! {" [. D8 J; Z& b
prhs 指向输入参数的指针 pointer of right-hand side 指针数组 ~* {# j. s$ I: \: Q
- o1 U1 v" Y+ }; ~' u& |9 a6 R
详情参考:
0 ^! d2 ^7 F! W5 w
# Z7 [5 e5 W9 l1 s p- Matlab参考-MEX库
- MATLAB中mexFunction函数的接口规范(转载)
- Matlab与C语言程序的应用编程接口
- matlab和C/C++混合编程–Mex# [, `1 M: O; S7 I$ g5 X3 S
4 p4 N$ k- t+ p4 t g+ C7 |% C9 R- \& h2 [/ k
编译多个c/cpp文件6 ~# B; K# ?1 f0 j5 `- [
假设A.c调用B.c,B.c调用C.c
& Y0 W9 ], v5 L可以使用如下命令编译:
F& z8 r: t- _( N8 q6 A% C* P0 Z5 U4 _- a: X
mex C.c
' N' r3 a2 i, C1 ~! Bmex B.c8 q3 _9 Z4 K8 d$ _2 F$ X
mex A.c' o* m5 O1 U. l/ [" N
4 c( C; R9 a b# X5 u4 C* e8 G6 B或者
+ X3 f" `2 b6 R6 H7 G
) _& B5 b( w: qmex A.c B.c C.c4 X! e' m' p6 ?3 n' k% L- l O) P: b
6 V$ a' A% D. ?' ?' B5 N5 @# \
: t" m: K5 O$ u8 g3 M2 g ^; o# N
: w; k; B; G6 G: i |" X) M; X! ~# `# l3 o. s; m& b( ?5 v
- s3 @5 s9 ^/ j, i1 `" s
$ O; @ F$ V9 ^, Z& T |
|