|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
说明/ b4 n' c* `4 x0 W0 P9 l6 D
Matlab混合编程. {2 ^5 u6 e# _8 m+ Y
下载与安装编译器
% }, {, x! G M5 ?. R Microsoft Windows SDK 71CC
! B" ]" l' d+ l! I* I TDM-GCCgccg
3 ]$ A/ R' q8 H/ l9 p0 [ For Matlab 2015' w# W( V! n" M: Z5 e
For Matlab 2014" A* A2 k! l$ O+ _) B
选择编译器
9 T6 E2 v2 l& W; ~; P4 s2 P6 m 编写ccpp文件
9 D+ x2 s/ @- y$ s7 l mexFunction函数介绍) ^9 W* {: w/ J1 B% x
编译多个ccpp文件
1 a5 n6 a* b( {2 y/ Y, }7 ]8 x4 x9 Y0 _
: p5 N" W6 U+ ^/ G! A2 m+ T: f说明' x& M, t7 L U' p4 ^
记录本人在Windows下,使用Matlab 64-bit 版进行混合编程时遇到的问题,主要记录编译器的安装与简要的混编过程。4 E$ W0 U1 E3 t% M
' z+ E5 i: k* c1 G- 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)7 n/ v" b& e8 ]1 V8 \4 `
2 U7 Q3 }. w1 b, B& g6 d( S! ?4 H9 f. L0 p8 O
) \# Q0 N9 j8 U1 M8 S0 X
Matlab混合编程% E8 b! T% D( v: Y2 w9 i1 d$ p
下载与安装编译器* G; {2 F' Z! ^+ C0 t6 o
Microsoft Windows SDK 7.1(C/C++)0 E" y3 j( a' I) {
点此Microsoft Windows SDK for Windows 7 and .NET Framework 4 (ISO)打开下载页面,是镜像文件,选择64-bit版,文件大小500M+,全部安装需占磁盘近2G。0 D8 f5 K! u2 U2 M7 L/ F5 D
% l6 p4 p0 R1 C* K& ?& i9 J* C
下载完成后根据提示安装即可,如果出现问题,安装失败,参考:Problem&Solution 部分。3 t- h% ?, @' A- z) l
, l5 a0 E& i! u7 ~9 d
TDM-GCC(gcc/g++)
: t9 x$ E* {" _7 w2 RFor Matlab 2015
8 j9 Y( j. ]+ w. P( VMatlab 2015已经开始支持GNU编译器,具体参见:Supported and Compatible Compilers for R2015b,安装方法参见:Install MinGW-w64 Compiler。, J' i) R1 [% u7 Q. G0 Z# N& m
2 ~4 f, K0 I/ P- 注意,MATLAB 2015现仅支持GCC4.9.2,在安装TMD-GCC时,不要勾选更新,如下图:& D7 y" i$ E& L
! O+ f- S! r% r4 h+ p% R- y
3 z, \ k& D2 v
3 [! B( R7 o4 n1 X3 h- 然后,还需注意的是安装路径不能有空格;
- 需要添加系统环境变量MW_MINGW64_LOC=your tdm-gcc path。
- 重启系统和MATLAB后,输入mex -setup显示:
4 s9 O( {6 s7 |4 M" | 9 X0 e. s+ i8 q/ k( v0 m
( Q: E. c5 L5 e+ Q
1 o6 s2 ^# | V) o. `! \ h, k% E至此完成!
- D! h3 z# Z! c7 H! ?" w* p
6 @) _$ _+ x; @0 vFor Matlab 20149 t5 N4 x3 p+ I! L6 W
如下文章针对于MATLAB 2014a。, Z4 Q: p3 d8 ?, E. P3 \4 y0 f
: p, r% q! i7 C+ H# V点此tmd-gcc打开下载页面,选择64位版本,40M+,全部安装占用400M+磁盘空间。
2 F1 v$ j$ y1 ?* ]6 _" J' w) s" ?' I( z" J5 h
根据以前使用经验,安装路径最好不要有空格中文。* @% U& r+ J" g! @. S) ~- v
5 _6 l( D% J4 A/ A6 m" g7 f
安装完成后,开始 -> 运行 -> cmd打开Windows命令窗口,输入gcc -v,如下图所示,显示安装信息,说明安装成功:
* U2 z/ s: @0 S" c' l
. V/ l) T# A) u5 ^
* O* t$ D# n# W3 W# l$ N" i
最后的战斗:
& P+ K4 A5 ~6 o1 F$ P& I& F8 z8 s3 }因为Matlab不支持GNU的编译器,还得做点事,下面的方法来自Using GCC (MinGW) as MATLAB’s MEX compiler 中的Bogdan的解答:1 M7 |4 |& O) V) c
2 o8 I0 c( W% L9 ~: ?
下面的代码是从Bogdan主页上下载的mexopts.bat文件代码,使用时需要做一点小小的改动。
5 B& B0 J/ n t/ J) F( H5 `( y) s
) I& y! b W5 X, A在下面的代码中找到:set MINGWPATH=p:\mingw64这句代码,将其中的路径p:\mingw64替换成你的TMD-GCC-64的安装目录,如我的是:E:\devtools\TDM-GCC-64,然后保存并将mexopts.bat文件copy到计算机如下路径(复制下面的路径地址,粘贴到资源管理器窗口地址栏,回车即可):, m+ Y; ^; C0 I. l' T$ H
6 m0 U+ f( h0 G Q# ~/ U8 l9 d%USERPROFILE%\AppData\Roaming\Mathworks\MATLAB\R2014a\
5 f# C+ g: y1 w. E$ \7 F
* X- S% l/ X9 s) L下面是代码:' {2 }! S4 H( }9 }" h7 x
& B1 `0 [5 E' g8 c; X@Echo off
: ^6 m4 X- K9 [ N
; d% r9 f6 \3 F7 s0 K( u:: NOTE: this is actually not a proper .bat file executed by Windows. MEX
0 z! {2 L' r9 v4 t. t! E% _* v:: parses it and only understands a very reduced set of commands:
" U% m5 f1 }/ J0 H* z$ Q9 F:: "set" and "rem" apparently, everything else is ignored (behaves as
1 Z, b3 c# e! x9 I:: "rem"), so don't do any fancy batch stuff in here. There are some
1 r& E o P5 ?8 K6 C" R# A+ n:: undocumented special vars you can set here that will trigger MEX
- `. m7 o0 x' M2 F* S4 a9 Z:: to do fancy stuff.9 x8 x7 Z+ C$ n) x9 @0 \2 W
; `& u4 m& B4 ~
:: You can use MinGW64 builds (win32 threads + seh unwinding) from here:! }" e/ B5 t9 ~
:: http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Personal%20Builds/mingw-builds/
8 c+ D9 a6 p( H' }( Z9 L- n# Z1 d' |, ^$ Y- J! |' I2 t% y
:: Tested with the following:- c0 D4 p2 u7 O! h1 I! M
:: 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 P$ E6 w5 N) }. Y
2 m# ~' ]2 l# s, D7 r
:: Set this to your Mingw64 top folder, where you extracted the above
4 ` I, V! T! `set MINGWPATH=p:\mingw64
4 s. a6 r' s% c* l4 ^* C0 B
! h& ^6 W+ z& ?' ^:: Leave these alone unless you know what you're doing.
+ l: {" {" ?- x D4 H: v7 b3 ?set PATH=%MINGWPATH%\bin;%PATH%
, _" _+ \. E, u7 bset PRELINK_CMDS=echo.>%TEMP%\mexstaticlibs
# Y: I( ~' ]* M. w% \1 ^- s+ y' e
:: You can have MEX run some commands before calling the linker.1 ]6 U1 f N2 t0 r& Q6 r
:: The two examples below will cause gcc to output the full path to some4 s& p8 J& E. i$ U F
:: static libraries so you can link statically to them (see the- B. o$ [, F2 \9 U/ m$ \1 y
:: LINGFLAGSPOST special var below). You can set any command here, however.* c- [7 V4 c, c" |6 g, R. H1 S
rem set PRELINK_CMDS1=gcc -print-file-name=libwinpthread.a >> %TEMP%\mexstaticlibs
1 u- Y) N5 F4 F5 @) ? Z: Jrem set PRELINK_CMDS2=gcc -print-file-name=libquadmath.a >> %TEMP%\mexstaticlibs
6 N1 M! v+ x) I; f$ g+ Frem set PRELINK_CMDS3=...
4 X: \$ p9 ?0 ]' _
1 P! j4 E+ ^% |) n:: You can have MEX run some commands also after calling the linker
7 v/ Z- l3 t, B:: (e.g. upx compress the output .mex)
8 G) u7 ?, i( A; Drem set POSTLINK_CMDS1=upx -9 "%OUTDIR%%MEX_NAME%%MEX_EXT%"% [! B* p8 a7 n2 \1 ?. j' o$ P0 j7 T
rem set POSTLINK_CMDS2=...
$ u6 E) p$ P$ r g8 p' @0 j5 x% _5 o
:: You can change these if you really need to.
* v5 b1 R* Z i6 zset COMPILER=g++: p% H3 n6 C& Z9 O# G2 s' f, J
set COMPFLAGS=-c -I"%MATLAB%\extern\include" -DMATLAB_MEX_FILE
# `, ^, Z1 D- [( ~set OPTIMFLAGS=-O3 -funroll-loops -DNDEBUG
. k" O. n# {& N4 a2 `" Gset DEBUGFLAGS=-g( g/ f" K" F/ u. y
set NAME_OBJECT=-o
( g4 {# r- D0 A, ?8 q8 c: p6 X% K+ K, f2 R* Q0 R# K3 d8 Q' e
set LINKER=g++: [6 h6 P* g- x, ^; e
set LINKFLAGS=-shared -static-libstdc++ -static-libgcc -L"%MATLAB%\bin\win64" -L"%MATLAB%\extern\lib\win64\microsoft" -lmex -lmx -leng -lmat -lmwlapack -lmwblas) [9 K, X/ M2 ^) H3 c: `6 a
5 S: g8 z9 W/ @; J' u
set LINKFLAGSPOST=@%TEMP%\mexstaticlibs5 B3 H: D: e" X
set NAME_OUTPUT=-o "%OUTDIR%%MEX_NAME%%MEX_EXT%"% ]3 t; O; i7 H+ o
3 L2 d! p+ M9 U* F9 X
( u ~. W+ I# _' {9 N3 b
:: EXAMPLES
+ F/ }1 R, D2 z' @# M1 p5 l6 D:: ========
2 U$ I& K5 t/ Q0 m- _& i, u/ p% }9 z# V
:: You can compile simple files using "mex file.cpp". To support more than 2^32 elements, use0 r5 }# ? Z# M# [
:: "mex -largeArrayDims file.cpp" ... use this by default, unless you know what you're doing.
2 G! }+ {( A. l# Z* P5 T) j, }- Y1 u' `2 Y; [0 ~
:: To add include dirs, lib dirs, or compile/link flags, do:- z/ p$ g" Q) e
:: mex COMPFLAGS="$COMPFLAGS -std=gnu99 -Ix:/include/dir" LINKFLAGS="$LINKFLAGS -Lx:/libs/dir -lmylib" -largeArrayDims file.cpp/ E2 [ M& S4 D, n0 J
- r5 I" I# V$ I9 H9 R
) m6 D N$ f: b5 b% I选择编译器 d' v u3 z. D- c; Y$ e& D2 f: u
- 查看可用编译器:使用mex -setup查看可选择的编译器,如果没有需要自己安装,如果已安装且只安装了编译器Microsoft Windows SDK 7.1(C/C++),显示如下结果:
/ {5 O6 e9 d+ Q- w2 b5 \
- 选择编译器:使用mex -setup lang选择编译器,如mex -setup C++选择C++编译器,如下图:
9 ]6 S y9 W8 c
- 如果你也按上面TDM-GCC(gcc/g++) 中讲的方法,配置了TDM-GCC-64位的编译器,那么,你会发现结果如下:
$ ?4 i, F0 G1 `# G
4 J# G, s7 l" c( n) O& g
& P7 Y4 a/ ?0 }! I \2 d3 n' \ k: P$ g
刚开始我也以为不能用,后来试着编译了一下,竟然可以!
$ j0 H+ v3 x2 K! S: w# D
/ {0 m3 q, r; T1 ^% N) n% L
DT.c文件中重复定义了无穷大,注释掉,就没有提示啦!
! d; z; x" L7 G" a9 x# P$ t7 `! _1 u/ e( f0 {3 }9 X7 @
9 t: j7 m4 M1 J编写c/cpp文件
1 b0 `; j5 ~5 i0 V* F6 @/ Q与普通的C文件的编写有两点不同:/ k b& I! U5 f4 E" p& z( M
: X+ f( x* [5 a" P: Y- 包含mex.h头文件,即:#include "mex.h";
- 编写mexFunction函数。" z' t( ]7 s) g0 e( k
6 z/ P. l8 ~0 X% s0 b9 {
/ q0 F O' ^4 D* [
下面以一个求和的例子说明:1 {$ H) C. U. @+ ^5 P, C* T
~# a( e. N7 s" f2 [
#include "mex.h" // 使用MEX文件必须包含的头文件! i) n) L/ W- t6 c* T5 K- {
// 执行具体工作的C函数6 E2 w8 ~- @/ i/ `0 ~9 M2 Q
double add(double x, double y)
% |8 n6 x K* Y! }- B{. g2 _7 {! n/ a* n, P
return x + y; W9 N+ Z" ]0 i( _: I+ U6 k3 o
}
, W% ]( ^( ` ]2 l7 Q; V- \4 c5 B// MEX文件接口函数
, m. H/ ^ {5 H9 \void mexFunction(int nlhs,mxArray *plhs[], int nrhs,const mxArray *prhs[])
2 z1 G1 u1 c! ~7 a+ I- S8 `4 j{
" V- E9 s: s+ W5 O double *z;- u. E+ t. y- s* Z$ F
double x, y;
' N& j* y! f: B% H* G5 m) R o1 ` plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);& @* P @7 g' A3 J3 ^9 g1 N
z = mxGetPr(plhs[0]);
0 Y) D, |7 w% ^$ G9 M, ?! z x = *(mxGetPr(prhs[0]));6 ^/ | N& W: V
y = *(mxGetPr(prhs[1]));
0 J M( M) b- O0 M1 T3 P0 [ *z = add(x, y);6 N o) P9 @0 z/ w# Y" Z! F
}* z$ S! Q6 W/ ?1 L
6 A6 X' w: g5 ~5 C
( v) D1 k4 e1 g! L0 V+ o+ I( r+ Z7 WMatlab命令窗口输入mex add.cpp,运行结果如下图:
1 w6 f6 M& T/ S9 r
0 h2 Q* G6 k% n W$ V3 t8 y# e k7 s4 O: h; V( c( |& X
在Windows上编译后生成mexw32和mexw64文件,在Linux上编译会生成mexa32和mexa64文件。$ A* R1 V$ T9 |8 w) z
/ e; t ]7 q7 g: l- V) umexFunction函数介绍
3 |2 P. o3 e1 F+ H' Z- NmexFunction函数接口如下:
, J# b; X, z5 L! A0 B
; S' H4 }. ^9 T, t# \! K' Yvoid mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
' I1 [5 L2 d% {$ p5 e, t K: V8 }3 A$ z4 z0 N
可见,是没有返回值的,其实是通过指针数组plhs传递的。它共有四个参数,即左边的输出参数及数目和右边的输入参数及数目,具体参数意义如下:/ y% Q2 F' _+ N8 u% _. X: Q
f" w) ?0 M% g7 `; |0 H
参数 意义 英文全称 类型1 ^& O* R% R. u& I2 M6 l6 [0 u
nlhs 左边输出参数的数目 number of left-hand side 整型(int). a( U7 n& j8 A$ {' e) w+ o; w4 d
plhs 指向输出参数的指针 pointer of left-hand side 指针数组
% q7 o/ Q% x G' c" [nrhs 右边输入参数的数目 number of right-hand side 整型(int)/ h+ U) l+ K/ n8 F' c
prhs 指向输入参数的指针 pointer of right-hand side 指针数组1 i5 X, P3 ]! s* P- H
4 Y+ I; Y1 ~. h7 K. R" ]+ Y
详情参考:
! Q/ Q0 Y- ~7 [! z, @) L7 b8 f3 \& p" R5 V2 w! p! P ^5 Y
- Matlab参考-MEX库
- MATLAB中mexFunction函数的接口规范(转载)
- Matlab与C语言程序的应用编程接口
- matlab和C/C++混合编程–Mex
% `+ u( r6 H4 N" S 8 l) \0 F) b2 ?$ K5 A* o& t: z
6 x0 m( v- e4 A7 P+ }$ {4 N编译多个c/cpp文件
8 y0 N3 x/ k: x2 t" f假设A.c调用B.c,B.c调用C.c
) c: N8 ?, n% L可以使用如下命令编译:9 n4 Y+ y9 r- s: a
6 p* o- V7 I: z' G9 M, Y( i& J2 F4 Kmex C.c
, S1 j7 X% A& q! e {% l# S1 Kmex B.c
- {' t$ C4 k* w3 y0 g0 mmex A.c9 G4 n* D9 r- r' c6 H, w8 K" t" O
8 O1 Y3 F' @/ V1 f' A
或者3 a6 @1 S7 K2 V, A" k
# s$ y* `* j: V
mex A.c B.c C.c
: W& I5 h* ]5 Q4 V
6 @' Y- {5 z+ c3 K" n" G$ b8 U3 _3 t6 `
- f, q$ O+ _$ T$ o0 |" N
" M1 ^6 z" n0 S$ R! t" a) f
8 ?5 R( @ J @4 B7 W! }5 F. G
% D/ ?( S" t7 | |
|