找回密码
 注册
关于网站域名变更的通知
查看: 368|回复: 1
打印 上一主题 下一主题

Windows 64 与 Matlab 64 MEX混合编程初步

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2020-5-7 09:21 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
说明3 Y8 |# S, w- E6 W1 u2 W
Matlab混合编程
# _* M! A: @8 U) Q/ e2 l! i       下载与安装编译器9 ?# w2 C: g* [) u6 x
              Microsoft Windows SDK 71CC7 N9 F8 x1 D+ h. \
              TDM-GCCgccg
+ @( p6 s1 I3 i- f% q                     For Matlab 2015
+ ^( Y# t  K3 Q1 f( h4 C( C                     For Matlab 2014
+ B% |5 E+ Y3 v) a) y" n              选择编译器
# L! O, ]1 l" V3 ?% `              编写ccpp文件
/ e1 R+ f" Q+ B9 [                     mexFunction函数介绍3 [6 l2 |9 x% W5 d  e
              编译多个ccpp文件
% s# Q- \% R( `+ r0 A3 w" B! Z5 }9 @  I5 N; O1 l  ^/ j5 K

1 f4 w& e" \( i  t说明) o  q0 t( z5 ]5 V' n
记录本人在Windows下,使用Matlab 64-bit 版进行混合编程时遇到的问题,主要记录编译器的安装与简要的混编过程。
1 Q: T& W) b/ \
( h( [3 i9 q2 C) _7 @
  • 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)% W& e1 g. T8 y+ f, S) `; y

2 _. r; ?; z% b; u! ?9 ^2 B
6 k+ ~" b( B  H. F" `" J3 ]7 C
; ], C7 K. D$ v( c; zMatlab混合编程
* D2 f! R" i9 p( Z1 {5 E下载与安装编译器& N, K) e' N- q) w2 E" I) y) n, }' T
Microsoft Windows SDK 7.1(C/C++)
+ m' m, \$ P& `" H5 p点此Microsoft Windows SDK for Windows 7 and .NET Framework 4 (ISO)打开下载页面,是镜像文件,选择64-bit版,文件大小500M+,全部安装需占磁盘近2G。
) b- |# y( F' Q, f' i& Q3 n) s. o2 M' N2 r8 z; ~+ z9 G! K
下载完成后根据提示安装即可,如果出现问题,安装失败,参考:Problem&Solution 部分。  o- I7 M; ?: B% t4 c: G
  d6 d: Q# ]0 e, j! e  B& `
TDM-GCC(gcc/g++)% W3 |0 y' j2 L7 N& |
For Matlab 2015
2 [+ T  R7 w, i  O+ [+ OMatlab 2015已经开始支持GNU编译器,具体参见:Supported and Compatible Compilers for R2015b,安装方法参见:Install MinGW-w64 Compiler。
. d/ M& }8 k5 y: u8 M6 ?0 L2 `
% L* W& e  t& u) v7 n: n7 U4 N9 s5 U
  • 注意,MATLAB 2015现仅支持GCC4.9.2,在安装TMD-GCC时,不要勾选更新,如下图:
    " B" C& ~9 D0 w. q  ]' Y. n

- K- t) S: l  ^5 D; ~
- g9 m& n3 ^% q& P$ ?0 G4 [5 \. ~- u; l0 K# O! D8 E5 Z* k
  • 然后,还需注意的是安装路径不能有空格;
  • 需要添加系统环境变量MW_MINGW64_LOC=your tdm-gcc path。
  • 重启系统和MATLAB后,输入mex -setup显示:
    - \) Y6 S% `4 `  |( I, Q, v

3 R( s1 Y: w6 Y8 m. r; G  ]  L
6 f. X, K+ t2 w3 D
) i) D* Y4 ^* W0 m$ C1 m至此完成!
5 ]  f; g+ E4 |+ F% {* m5 p, `
% r" N0 J# S( VFor Matlab 2014! x6 k9 ?% G, J7 ~% [6 D
如下文章针对于MATLAB 2014a。1 b" D/ _! H- l$ a4 }% [# Z4 l

. L9 b3 @% g' Q$ d! w0 Z0 W8 f, n点此tmd-gcc打开下载页面,选择64位版本,40M+,全部安装占用400M+磁盘空间。
" Z' I) o) Z. Y* C" J* x' B0 Z: z; x( a. Y: {  U
根据以前使用经验,安装路径最好不要有空格中文。8 y+ `7 U& @* {' R
6 \7 `5 ~3 I' F  m8 ~+ O( E
安装完成后,开始 -> 运行 -> cmd打开Windows命令窗口,输入gcc -v,如下图所示,显示安装信息,说明安装成功: 5 {4 @7 V9 J1 m+ h$ k! z. R
2 Y* W; f' n, E) s8 s
1 V: n* U" G. k: O" g) R  U4 u3 C
最后的战斗:
$ E5 D8 q0 w& b" B& N5 G% u因为Matlab不支持GNU的编译器,还得做点事,下面的方法来自Using GCC (MinGW) as MATLAB’s MEX compiler 中的Bogdan的解答:
; ^+ x1 U: n. C5 ^' W' P9 s5 z) K
, n. w# i0 o' n! q& b下面的代码是从Bogdan主页上下载的mexopts.bat文件代码,使用时需要做一点小小的改动。, n: N8 V: h# I- b
5 \7 S2 Q. X! K
在下面的代码中找到:set MINGWPATH=p:\mingw64这句代码,将其中的路径p:\mingw64替换成你的TMD-GCC-64的安装目录,如我的是:E:\devtools\TDM-GCC-64,然后保存并将mexopts.bat文件copy到计算机如下路径(复制下面的路径地址,粘贴到资源管理器窗口地址栏,回车即可):* v' F0 J& ^4 a* J5 S3 c

& G* I8 \& U" J2 O5 T$ n- w%USERPROFILE%\AppData\Roaming\Mathworks\MATLAB\R2014a\
0 z3 R! g# ~9 L/ U6 N! d3 v6 r8 S/ Z6 Z+ C5 L
下面是代码:
& f" {/ z6 {0 i( O- i4 J& H7 J7 `/ _" }' x6 `4 A
@Echo off
  N9 W; @( L3 ]
. L$ n, I2 m$ x:: NOTE: this is actually not a proper .bat file executed by Windows. MEX: z3 M- T" S, w; B0 \/ X! W. A
::       parses it and only understands a very reduced set of commands:3 O8 U( {/ |1 z! ?2 M7 T# K3 l
::       "set" and "rem" apparently, everything else is ignored (behaves as/ m1 A9 v6 P3 D6 V0 E
::       "rem"), so don't do any fancy batch stuff in here. There are some! U3 u! Z; c& {/ A* ]
::       undocumented special vars you can set here that will trigger MEX4 z; w( _$ \  a
::       to do fancy stuff.
# ~" F. d# `- n  U2 y6 q
' I; l4 o  {# V5 v4 M! A" w:: You can use MinGW64 builds (win32 threads + seh unwinding) from here:
  K6 g/ g& b* x" l+ }6 w' d+ q:: http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Personal%20Builds/mingw-builds/" z3 D! A  n+ U; g* R* ?

8 l0 e3 g. `* d! Y9 ]4 x, U:: Tested with the following:$ k7 a6 N3 ]% O% v
:: 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' e' L, Q2 `! ~
6 I  ?( ]/ K) f
:: Set this to your Mingw64 top folder, where you extracted the above
! [6 z) O2 `6 f3 ^2 w. s2 F/ `set MINGWPATH=p:\mingw64  I/ B: V- a" u9 v4 y

) d! E4 ]4 {" ~0 o5 s2 @:: Leave these alone unless you know what you're doing.$ N" p8 ?6 x6 T$ R" g
set PATH=%MINGWPATH%\bin;%PATH%
& p7 L) H1 h7 s/ I3 i, cset PRELINK_CMDS=echo.>%TEMP%\mexstaticlibs& E& Y! L7 X. N- S+ Q! {7 k

' [% G! A. y- O- X:: You can have MEX run some commands before calling the linker.
- \# x/ X3 E2 j$ M& H( m:: The two examples below will cause gcc to output the full path to some
- x( E5 |: L' ^% Y- t$ M:: static libraries so you can link statically to them (see the
/ {9 p6 u8 t# j2 L# z1 p3 i, G3 v' O:: LINGFLAGSPOST special var below). You can set any command here, however.
# c# B1 u, r5 N! frem set PRELINK_CMDS1=gcc -print-file-name=libwinpthread.a >> %TEMP%\mexstaticlibs$ H. {. L9 G8 }1 x
rem set PRELINK_CMDS2=gcc -print-file-name=libquadmath.a >> %TEMP%\mexstaticlibs3 u& p* Y: D% V
rem set PRELINK_CMDS3=...- z8 E& ]) d; |8 J

% D! s  B$ r& @5 M; \:: You can have MEX run some commands also after calling the linker
9 E1 `3 |. {  ]* A' j:: (e.g. upx compress the output .mex)
, r% y( G7 q) ^1 ~/ Vrem set POSTLINK_CMDS1=upx -9 "%OUTDIR%%MEX_NAME%%MEX_EXT%"0 p2 M& o7 k) W; O& s. W2 E8 s( K
rem set POSTLINK_CMDS2=...
1 n; F) y+ u7 G. V% o/ c# T! V; z* P; \& D) W$ c1 O0 c
:: You can change these if you really need to.$ m' f/ j7 R3 r3 J  d# q
set COMPILER=g++
2 `( n7 O8 `3 fset COMPFLAGS=-c -I"%MATLAB%\extern\include" -DMATLAB_MEX_FILE% w& A( ~0 x$ t% H( z, d% `: |
set OPTIMFLAGS=-O3 -funroll-loops -DNDEBUG
' B1 ?$ M+ }, I) l+ mset DEBUGFLAGS=-g. n3 v6 d4 r, F! f* x/ k1 J
set NAME_OBJECT=-o
' m6 e, l/ A$ G3 ^: v+ M  y: f
" R9 x; W$ s; `1 h* Y; @& uset LINKER=g++
; A  P1 k9 P$ m/ \0 kset LINKFLAGS=-shared -static-libstdc++ -static-libgcc -L"%MATLAB%\bin\win64" -L"%MATLAB%\extern\lib\win64\microsoft" -lmex -lmx -leng -lmat -lmwlapack -lmwblas3 P: w4 d3 l/ b$ V' s% D! D8 J5 S4 z
) q  R9 O* A. V# K4 d6 B; T; Y$ k
set LINKFLAGSPOST=@%TEMP%\mexstaticlibs
- R' o4 y9 I0 P5 Aset NAME_OUTPUT=-o "%OUTDIR%%MEX_NAME%%MEX_EXT%"# x6 y& c; N0 j: m; F8 z% L

4 l& u1 r  F4 b& F
5 m4 _, b% y/ S4 V5 L& a  p:: EXAMPLES
9 O/ E1 T; ?5 u2 a2 w2 h:: ========! s& {$ F! H4 s0 W; y" y3 H, \

& X0 |3 C2 F9 ]' C& y' Y:: You can compile simple files using "mex file.cpp". To support more than 2^32 elements, use2 Y% Z; T8 m, C9 C  [
:: "mex -largeArrayDims file.cpp" ... use this by default, unless you know what you're doing.: g; y# H$ I7 D( n
$ Y2 x1 @  S& Q5 l) E
:: To add include dirs, lib dirs, or compile/link flags, do:, h+ F" Z2 J3 `
:: mex COMPFLAGS="$COMPFLAGS -std=gnu99 -Ix:/include/dir" LINKFLAGS="$LINKFLAGS -Lx:/libs/dir -lmylib" -largeArrayDims file.cpp
( T& r8 c2 v3 w: ~' ?* _' t3 g: U, {$ T) e9 p* V; u
) X' o8 i- M0 x+ q  n: c
选择编译器( U; @' v3 M8 z" @5 y  E- K
  • 查看可用编译器:使用mex -setup查看可选择的编译器,如果没有需要自己安装,如果已安装且只安装了编译器Microsoft Windows SDK 7.1(C/C++),显示如下结果:
    " ^# m5 o, l) b- N. `
  • 选择编译器:使用mex -setup lang选择编译器,如mex -setup C++选择C++编译器,如下图:
    7 N; N3 u0 Q2 t/ ~& M* Z* {# Z
  • 如果你也按上面TDM-GCC(gcc/g++) 中讲的方法,配置了TDM-GCC-64位的编译器,那么,你会发现结果如下: ( i" a/ l* J* S6 w% M0 m
      f% S8 r' |( T( e, z) @
. F: P/ F+ g4 _1 w7 K

0 D. v  t1 v  v% \: n' }; m2 k刚开始我也以为不能用,后来试着编译了一下,竟然可以!
% s9 x0 K2 o# N& W& F# x8 @6 S6 Z       & E5 x- L/ a& D
DT.c文件中重复定义了无穷大,注释掉,就没有提示啦!# N% ~. T9 t; H# t9 W9 G2 f

1 I. O' U6 K4 \. @1 T
. r) N% Y/ N( U- z* F1 i& {8 Y- y编写c/cpp文件
7 t' P% `" {' |8 a# P8 _; A与普通的C文件的编写有两点不同:
# _( V! ~# w+ |( l4 k2 i2 Y8 U% w# ~
  • 包含mex.h头文件,即:#include "mex.h";
  • 编写mexFunction函数。  o8 Q- n* x5 H
1 ^: \, S. t* ?) H* w
3 o! [, o0 C% C2 \2 w9 v9 s
下面以一个求和的例子说明:8 T1 I  ^1 S: I5 t1 W; q
9 m+ v2 A- ]6 s- I
#include "mex.h" // 使用MEX文件必须包含的头文件* ^  _3 c& V0 K; c) u. f" i% t
// 执行具体工作的C函数" {. ~# z' X" U- g, X' \2 w8 H+ `, S) ]
double add(double x, double y)
; r8 j; n* C. Y' v" H$ m6 o& m{. T8 R6 L0 r  [) y
    return x + y;% E* B# B4 g1 k  n! G" p
}
7 r! h+ Z( j2 y6 {$ @: {' h// MEX文件接口函数7 g. Q9 A/ ^: c: p$ d  I8 {, `8 |
void mexFunction(int nlhs,mxArray *plhs[], int nrhs,const mxArray *prhs[])+ t7 l" ]( o' g7 E# }
{! W# H0 c6 \) c$ P3 g; `) g
    double *z;! I8 U+ Z" p* W- G& Q) C1 U# u6 Q: D
    double x, y;
+ O) Y7 ?1 V$ i6 o    plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);+ w# o6 {/ O7 v2 {1 K
    z = mxGetPr(plhs[0]);' ?" I& w$ W7 a/ ~% N
    x = *(mxGetPr(prhs[0]));$ Q1 V! H' }1 J' n0 ~! o9 b# K
    y = *(mxGetPr(prhs[1]));1 `9 U' L0 }) i/ ^
    *z = add(x, y);
7 ^7 D* g  {  U4 B) z, H0 n3 m; I: c}3 h$ M5 J$ f$ z! h3 j9 T, X0 a# d
' o, g, U& I% K% u- R, `
( S" G' v1 r$ {
Matlab命令窗口输入mex add.cpp,运行结果如下图:
) d  {+ _5 ~0 r/ j# O7 m  J 0 v2 F  t: P- E5 e/ W
+ t8 O8 k- q3 f4 }/ r7 @9 O& _
在Windows上编译后生成mexw32和mexw64文件,在Linux上编译会生成mexa32和mexa64文件。& p# W4 _5 T) b6 @$ U

, F8 f% H( s+ V6 emexFunction函数介绍1 E7 _# B# r8 {9 j) S
mexFunction函数接口如下:4 A9 B+ F3 Q; A; l6 \7 d. N& M

1 ^  Z, G3 K4 {+ G1 V9 \6 m' ^% fvoid mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])3 `4 E7 U# O; `8 X7 H
7 N: |: C- p2 Q" s
可见,是没有返回值的,其实是通过指针数组plhs传递的。它共有四个参数,即左边的输出参数及数目和右边的输入参数及数目,具体参数意义如下:
; z7 |/ t  V2 A  _9 E( O0 \7 A% H7 M/ F' t" n! a, C
参数                  意义                          英文全称                 类型
) l9 [, k' G, x# e/ u. fnlhs        左边输出参数的数目        number of left-hand side        整型(int)8 E2 {9 \7 M+ u8 B: E% t
plhs        指向输出参数的指针        pointer of left-hand side        指针数组
9 {5 T7 ?. \* U5 J/ bnrhs        右边输入参数的数目        number of right-hand side        整型(int)' }- C! r: L' G( @( `6 y/ O
prhs        指向输入参数的指针        pointer of right-hand side        指针数组3 b; |6 N+ ?0 ]3 W/ s; J0 r- h3 w

* y6 G1 F3 W' k0 Z% U详情参考:
7 r) X' F9 X6 T( ]& J+ J3 R5 x! }. F2 [3 o5 Q
  • Matlab参考-MEX库
  • MATLAB中mexFunction函数的接口规范(转载)
  • Matlab与C语言程序的应用编程接口
  • matlab和C/C++混合编程–Mex1 L) ~% H' C2 F  l4 K1 o. o

6 s' o1 f6 j6 x1 w$ @& G! e& a$ z6 m0 J9 V: z
编译多个c/cpp文件( @' l' n% N5 U, O' P
假设A.c调用B.c,B.c调用C.c
3 Y6 j$ J) [+ |可以使用如下命令编译:0 T; t& i' [0 L+ S, `% N

0 E8 N+ Y! D: y8 K% A* \1 R4 gmex C.c) ?! y. }: e+ `4 o5 Y1 n; A; [
mex B.c
4 P2 `9 e4 N4 w; a6 u, dmex A.c8 y  n2 w( O# `# }. j4 l
" I  D1 `( ]( G, v- {2 W6 ^" j
或者
  e3 ^6 i5 l+ n2 q( G1 b7 Y% ~0 S# ^2 l9 C0 ^4 J. U
mex A.c B.c C.c
1 f2 }: d2 m! l6 H2 j6 l( T$ P
; R. z+ T. u7 ]6 h+ I/ i+ O
/ s- l1 V# K0 B0 a" m# h: B& o: L6 u% M) x5 c  @- t
+ Q" O. c& n2 m

4 A$ I! p& u9 n# I; z/ G7 s( J! x! L1 T1 |

该用户从未签到

2#
发表于 2020-5-7 13:31 | 只看该作者
先收藏了吧
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-6-23 08:32 , Processed in 0.078125 second(s), 26 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

快速回复 返回顶部 返回列表