|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
说明
# ~: Q. P8 C! c2 @, Q1 F2 dMatlab混合编程+ n u- t- |% B# H6 l
下载与安装编译器
; n' k/ e) H+ l Microsoft Windows SDK 71CC
8 f7 h. k Z" i0 q( t9 g/ a; K6 S" P TDM-GCCgccg/ f) m* n9 @0 ]7 x: u
For Matlab 2015& l# K+ g' f5 A; p8 ^0 @
For Matlab 2014% \; Q3 w1 \7 u& A
选择编译器% P! j( n3 E g: G7 S8 ^
编写ccpp文件
& ~1 ?7 D# x0 \ f# S) }: G mexFunction函数介绍/ I( h- J3 g/ \6 Q
编译多个ccpp文件
- y- k( S* R" m I; _! k, k& c
8 ^# a7 ^, Z$ ?$ Q9 s# m
" Z+ K) X7 A, j# Q说明
: {3 K4 x* q/ w1 S9 U5 y记录本人在Windows下,使用Matlab 64-bit 版进行混合编程时遇到的问题,主要记录编译器的安装与简要的混编过程。" c7 E- n n: F- ^3 s4 {
) J6 a" k; |( G$ ~2 O) y9 `% }
- 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)# r6 d- [2 Z- ?% S
/ Q, ^- Y" ~. i2 o7 T: {1 H C0 a; v' o6 n# n( C
* m" h6 ^; L3 |" ?6 }1 R- ~$ }Matlab混合编程
8 H2 g6 f8 x. j5 _下载与安装编译器9 D, L( I) M* k' G
Microsoft Windows SDK 7.1(C/C++)) r7 Z% w8 _* B3 M! l" Y
点此Microsoft Windows SDK for Windows 7 and .NET Framework 4 (ISO)打开下载页面,是镜像文件,选择64-bit版,文件大小500M+,全部安装需占磁盘近2G。9 @6 S% `5 `/ K, b
8 P+ h! A! W5 F) ^% i下载完成后根据提示安装即可,如果出现问题,安装失败,参考:Problem&Solution 部分。
& \+ r. D1 M6 r- h, c
+ I$ V" K- U! s8 ~! mTDM-GCC(gcc/g++)
8 @6 n! g. R* I2 l8 ]( HFor Matlab 20157 c% d4 k9 D. }) `; p
Matlab 2015已经开始支持GNU编译器,具体参见:Supported and Compatible Compilers for R2015b,安装方法参见:Install MinGW-w64 Compiler。 |; l% c& B0 W: e
9 e8 z1 ^$ r/ d0 z/ c( ]$ q- 注意,MATLAB 2015现仅支持GCC4.9.2,在安装TMD-GCC时,不要勾选更新,如下图:
/ x1 s3 k1 T( E* n1 v3 M6 r
1 L# F4 f- ?+ a3 K
3 t2 W) b1 S: f* ]" v+ G( G
# J% ~: d/ K, t3 J) P$ o
- 然后,还需注意的是安装路径不能有空格;
- 需要添加系统环境变量MW_MINGW64_LOC=your tdm-gcc path。
- 重启系统和MATLAB后,输入mex -setup显示:
; j+ H+ m0 {! [/ I2 V% g/ v 8 W: ^, f" r6 ?/ F7 h7 E0 F, n
: ]: u2 \- P$ ~+ O% j3 L8 \
) r% D4 T! m, ~% j: g# w3 i6 y& {至此完成!
2 ~* p$ l! o4 k4 g; {! i: Z
& C# {/ X6 W, i( eFor Matlab 2014
% E7 Q0 _4 r$ u$ i7 M, G如下文章针对于MATLAB 2014a。
H1 N! F- w( m2 O3 w: u% K4 M2 A# M0 u# l7 g1 x
点此tmd-gcc打开下载页面,选择64位版本,40M+,全部安装占用400M+磁盘空间。
+ r; G# G# U3 {1 o- {2 [
; |7 V7 u0 o# d& W9 r1 r根据以前使用经验,安装路径最好不要有空格中文。! O' v3 @# D! P! D
9 v# n# I, D* l
安装完成后,开始 -> 运行 -> cmd打开Windows命令窗口,输入gcc -v,如下图所示,显示安装信息,说明安装成功:
* J; T( _, C1 b+ R* U
4 n6 o' S2 l; x5 V! q3 S+ f6 U; O, h8 `; `- t
最后的战斗: " S6 l( }9 L+ P$ A0 R3 j/ D; N
因为Matlab不支持GNU的编译器,还得做点事,下面的方法来自Using GCC (MinGW) as MATLAB’s MEX compiler 中的Bogdan的解答:
" b5 O; o& z/ q( J1 |! C3 x4 a' W S+ f# W
下面的代码是从Bogdan主页上下载的mexopts.bat文件代码,使用时需要做一点小小的改动。
2 @+ C! D. k& W3 K7 M, ]& @$ M! B+ U5 L
在下面的代码中找到:set MINGWPATH=p:\mingw64这句代码,将其中的路径p:\mingw64替换成你的TMD-GCC-64的安装目录,如我的是:E:\devtools\TDM-GCC-64,然后保存并将mexopts.bat文件copy到计算机如下路径(复制下面的路径地址,粘贴到资源管理器窗口地址栏,回车即可):5 Z8 X) e3 ?5 e1 R$ C; `
: }2 @0 _- _; T0 v7 ?* V
%USERPROFILE%\AppData\Roaming\Mathworks\MATLAB\R2014a\3 e7 n& [ t* v
@5 V! i6 U$ ?7 x" F下面是代码:) u3 W+ h! @1 X- U8 ^- W t8 K
6 ?2 F6 a9 L4 } c2 R# b0 h$ h1 Z }
@Echo off
4 B2 r, P* |$ }
+ A+ Y/ g8 k0 m:: NOTE: this is actually not a proper .bat file executed by Windows. MEX
' |" E8 ] l. T! A4 T:: parses it and only understands a very reduced set of commands:
+ L# [, f$ R0 J X0 p' v:: "set" and "rem" apparently, everything else is ignored (behaves as
0 G8 s Q. R3 K" P' C. h. P:: "rem"), so don't do any fancy batch stuff in here. There are some
& Q* \& A" u! O5 g9 \7 ]:: undocumented special vars you can set here that will trigger MEX" W% A x# M. A
:: to do fancy stuff.7 a1 l6 O Y; a6 n
2 z0 t) e/ w- }/ d
:: You can use MinGW64 builds (win32 threads + seh unwinding) from here:' K/ O. z/ z9 E* m& i& U
:: http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Personal%20Builds/mingw-builds/1 E; R( V4 _, [: a* A
4 P6 _/ y" o, b, r# ]
:: Tested with the following: a; N3 R$ c# h* Z+ I% Q# j( T% \5 s
:: 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.7z8 @2 ? ^6 Z. \" i& j* C- t" c
5 l# i3 h) \* p6 f- ^. Z
:: Set this to your Mingw64 top folder, where you extracted the above3 q& ~5 `% F K0 i
set MINGWPATH=p:\mingw64; l6 a1 H2 q" M7 M0 F
; s4 Y5 ~* ~% {6 y) ?* d
:: Leave these alone unless you know what you're doing.
. v% P$ T/ u2 a- Hset PATH=%MINGWPATH%\bin;%PATH%! P9 C# b0 R v0 p
set PRELINK_CMDS=echo.>%TEMP%\mexstaticlibs2 O- z) _, H9 l* d$ `$ l4 ~
* x, [7 s' y( a) K0 F& H. a# S, O
:: You can have MEX run some commands before calling the linker.
4 I8 B9 H. B/ V" w6 z* L:: The two examples below will cause gcc to output the full path to some
. p* B- l: u; u:: static libraries so you can link statically to them (see the5 G5 O6 X! O" [ M
:: LINGFLAGSPOST special var below). You can set any command here, however.
3 ? [& O& s0 e& X8 xrem set PRELINK_CMDS1=gcc -print-file-name=libwinpthread.a >> %TEMP%\mexstaticlibs
$ U5 Q' [0 h9 K' F/ E2 qrem set PRELINK_CMDS2=gcc -print-file-name=libquadmath.a >> %TEMP%\mexstaticlibs+ \" Q8 T1 @: U3 l1 I. J3 l8 C) x
rem set PRELINK_CMDS3=...9 A7 C# T# u9 [& h3 h
# w0 H- S6 o, f" z:: You can have MEX run some commands also after calling the linker
; u* K5 o, O1 T# z:: (e.g. upx compress the output .mex)
{ E; e; i' _. R' _0 \rem set POSTLINK_CMDS1=upx -9 "%OUTDIR%%MEX_NAME%%MEX_EXT%") t" s J7 @8 F _6 o+ u# ~; j' |
rem set POSTLINK_CMDS2=..., d2 @9 l, |. \8 ~3 d* T: U# i/ y( p
$ x s1 \4 _. p:: You can change these if you really need to.8 @+ ?9 T- i) c1 [' N; [8 f7 j
set COMPILER=g++
/ P m S5 Y1 q7 Vset COMPFLAGS=-c -I"%MATLAB%\extern\include" -DMATLAB_MEX_FILE! d( Y% J. l# ^
set OPTIMFLAGS=-O3 -funroll-loops -DNDEBUG; L; y5 ^+ d) k) Q4 k/ t
set DEBUGFLAGS=-g) v; X' v" J2 D3 N: e
set NAME_OBJECT=-o
# I' E$ \, L; h7 | G0 R/ N6 c+ R- l3 X# K, C( G
set LINKER=g++2 [. b, N" X6 [3 c! e a* D
set LINKFLAGS=-shared -static-libstdc++ -static-libgcc -L"%MATLAB%\bin\win64" -L"%MATLAB%\extern\lib\win64\microsoft" -lmex -lmx -leng -lmat -lmwlapack -lmwblas
V5 | ?/ J0 Z5 I1 j
( ?$ V; {; a7 Bset LINKFLAGSPOST=@%TEMP%\mexstaticlibs4 t0 ~4 P% K0 e/ _
set NAME_OUTPUT=-o "%OUTDIR%%MEX_NAME%%MEX_EXT%"
" m4 j0 b% n4 U& o; f( ~ Y
5 t0 z5 p2 D4 ~' V! O R8 D) Y* N$ q* c% ^ T( j
:: EXAMPLES
7 [ r, v/ e$ Q$ A; ?:: ========% _7 i+ U$ S' ]/ B
; G; F/ T0 `$ B
:: You can compile simple files using "mex file.cpp". To support more than 2^32 elements, use
1 |+ w/ }, C" ~& @:: "mex -largeArrayDims file.cpp" ... use this by default, unless you know what you're doing.$ h/ Z0 H4 N% x. ~9 O
( |7 a4 a4 s4 C:: To add include dirs, lib dirs, or compile/link flags, do:
8 Q$ O3 ~8 m+ R. i2 o2 ]:: mex COMPFLAGS="$COMPFLAGS -std=gnu99 -Ix:/include/dir" LINKFLAGS="$LINKFLAGS -Lx:/libs/dir -lmylib" -largeArrayDims file.cpp4 d5 d7 ^0 ]6 E2 A! M
# \- V. O1 A# \5 F& ?1 h
: v0 t4 }2 P, o& L" W7 P选择编译器
; Q7 L$ s6 P; I: s y( J1 `9 A- 查看可用编译器:使用mex -setup查看可选择的编译器,如果没有需要自己安装,如果已安装且只安装了编译器Microsoft Windows SDK 7.1(C/C++),显示如下结果:
4 M+ Z% N3 ~, l9 A' Y3 b
- 选择编译器:使用mex -setup lang选择编译器,如mex -setup C++选择C++编译器,如下图: 6 k) H. H7 q' z2 o6 F8 j
- 如果你也按上面TDM-GCC(gcc/g++) 中讲的方法,配置了TDM-GCC-64位的编译器,那么,你会发现结果如下:
0 W0 b* Y+ g9 D6 l
! x1 J u) G$ i , @/ C" I; b# I
1 C2 d% b$ J( E- f4 L( i$ ^
刚开始我也以为不能用,后来试着编译了一下,竟然可以! ; k2 K( P3 [, R) T4 _. I
5 ]$ G5 X2 M" P0 U( p' `1 E3 D
DT.c文件中重复定义了无穷大,注释掉,就没有提示啦! U# Q5 d; e- U4 D6 ?8 ~5 h
5 u( P" |* C, k: R2 Q) Z0 P
4 `. F3 @( n I, p
编写c/cpp文件
- f( F* k/ y$ o6 a3 w6 Y与普通的C文件的编写有两点不同:
$ F3 _9 l/ U0 Z' B/ F7 u" Q( A" r# c: T" l) l
- 包含mex.h头文件,即:#include "mex.h";
- 编写mexFunction函数。
5 @) }. e/ \1 n0 \4 L
. n3 C; D1 g7 s2 _, \0 L; T! l% l$ u2 U. j9 {2 {+ p: v
下面以一个求和的例子说明:
7 X U# v" x( ^9 e
! n! O: q+ d7 j" D: Q0 ^) X5 U; Q7 _#include "mex.h" // 使用MEX文件必须包含的头文件
7 |' Q2 e2 o) {! H% I// 执行具体工作的C函数2 A+ w6 R4 E7 u+ R+ Y
double add(double x, double y)
6 |1 C: s) B4 r6 \5 d{# p7 S3 r9 u. q" W( Q" ]! B
return x + y;( e4 e* A7 W+ T
}+ P; _9 k Q ^2 @3 e3 Q" e# l
// MEX文件接口函数" S- X/ i% r: O
void mexFunction(int nlhs,mxArray *plhs[], int nrhs,const mxArray *prhs[])/ @; a1 O+ r( n4 ?( C8 |
{4 q5 \4 \8 `! Y3 ]+ _1 |: `. {# v
double *z;* l# {9 K3 }' ?# m' y8 L% \* w S
double x, y; P% H- E ~* x
plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);
3 q6 y8 H& G, P+ M z = mxGetPr(plhs[0]);
* b# P @* D7 K$ Y, H x = *(mxGetPr(prhs[0]));
, U* K( V+ e. G y = *(mxGetPr(prhs[1]));) h$ o1 _* c0 J0 F8 S
*z = add(x, y);
7 w( D$ W( k1 P0 P& F}
& | F: l; |5 n; X, N- @: K& |: P% a7 _7 D: ]( L& W, H
6 o0 t) T- }! i0 U4 O o
Matlab命令窗口输入mex add.cpp,运行结果如下图:
i+ l- l/ F2 R& |6 t9 t$ b
% o) X* P, S6 h. G& g" \
! F+ b& I9 J R6 h) w在Windows上编译后生成mexw32和mexw64文件,在Linux上编译会生成mexa32和mexa64文件。0 [4 p& _8 f" w. I6 q* M! y
7 P* s h$ Y0 [2 r6 z
mexFunction函数介绍9 T# x& H0 n5 s* Y
mexFunction函数接口如下:" c2 I3 t [" a3 G
- R! h. p0 ?! U
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])6 o( E# z5 s- S8 K
$ Y; l+ Q3 W5 q. V( u1 l* w K" Q1 f. {
可见,是没有返回值的,其实是通过指针数组plhs传递的。它共有四个参数,即左边的输出参数及数目和右边的输入参数及数目,具体参数意义如下:
9 H! W6 U8 y. M. {
1 v# b% v( l: }+ W. \7 K0 ^参数 意义 英文全称 类型
2 P; n/ u# |+ k3 mnlhs 左边输出参数的数目 number of left-hand side 整型(int)3 m( x% k y1 K+ w8 d
plhs 指向输出参数的指针 pointer of left-hand side 指针数组) D2 f: S- B9 N6 y# |
nrhs 右边输入参数的数目 number of right-hand side 整型(int)1 Y, ]- V8 Z; a/ C# Z
prhs 指向输入参数的指针 pointer of right-hand side 指针数组& l$ k$ s( t) ^
3 T! R0 n4 B! e9 E4 d* ~详情参考:* }! J0 W7 s( X- _2 R+ g
/ P" l- L' ?3 x% [4 S. K, r
- Matlab参考-MEX库
- MATLAB中mexFunction函数的接口规范(转载)
- Matlab与C语言程序的应用编程接口
- matlab和C/C++混合编程–Mex7 j- E6 q" C6 N% \% Q. {" g
- ~6 M: V& C- c) |$ K8 N
5 z2 i$ W1 Q/ |
编译多个c/cpp文件# I$ t6 ]! K' L4 B6 k+ k6 D1 |7 g
假设A.c调用B.c,B.c调用C.c ! g' T5 A, G9 S
可以使用如下命令编译:3 q7 z$ b7 d8 ]1 O5 e
t- l) A* @! b9 r, P/ I% ]
mex C.c
' I. X+ L" f, c3 W2 c8 t5 |mex B.c+ U" P" H/ J; Z1 {) N8 x
mex A.c1 P7 C) Q" k& O9 W
3 a3 j9 g% e" L# q9 L% V3 O或者
8 U2 N/ [' }8 Q5 {4 _. q
5 o+ ~$ r( ?1 w, F! amex A.c B.c C.c) U5 ^, R! b5 @, V3 n- x
7 ?4 V/ X3 M% G5 q1 U/ |- W1 o! V: ]
2 N- X1 B& R- \
, w* X% ~; Z0 A. P T
/ ]1 F2 Z. T. e9 D. [( `4 Q# ?5 [/ _) F' Z/ [
% W* i9 ~- _8 f
|
|