|  | 
 
| 
matlab封装DLL动态链接库 再用VS2010调用(matlab VS混合编程)(转载) : U3 z8 K! |+ P: ~$ X: Z% c( ]
x
EDA365欢迎您登录!您需要 登录 才可以下载或查看,没有帐号?注册  v( r, U* i! R7 ?5 U
 整个配置调试过程使用的环境为matlab2011a(version 7.12.0.635),VS2010,操作系统是window7
 2 ?# N+ T. k6 b- b8 v+ t2 Z' x) }) Q
 一,设置操作系统的环境变量。
 2 ^2 t; |, \! a! \, s% t  I! _/ `
 ; M7 t- B- t+ K1 `系统变量增加D:\R2011a\bin\win32;D:\R2011a\bin和E:\Microsoft VisualStudio 10.0\VC\bin,这个分别是我的机器上matlab和VS安装目录下的路径。
 " X1 F! d& E& T9 {9 ?* ~) o! D( B- t( G; @
 系统变量设置完毕后需要重新启动计算机方能生效。" J' U' P8 s3 w) j* X
 
 3 k( [; Y5 v1 |二,设置matlab的编译环境
 % }+ V2 W1 `+ ^+ [
 0 B3 z7 H8 z' T; @+ x3 G) i在matlab中输入命令mex -setup,选择Microsoft Visual C++ 20103 R1 p6 S! q' o  j
 9 y1 R4 V4 }: x' i5 D7 e
 再输入命令mbuild -setup 同样选择Microsoft Visual C++ 2010. J# ?# W8 [0 L$ E7 A0 f5 `
 + F. w! y; h" n
 p.s. 这一步中,在我自己配置的过程中,matlab可以很容易的识别出机器上装有的编译器以及他们的安装路径,其中包括VS2010,选择它就是了。也许有的环境下matlab不一定能找出VS2010中的VC编译器,这个怎么解决就不知道了。
 , l! x# Q# c8 Z/ K2 X
 / @1 x+ c+ R& m' L, J三,matlab编译.m文件
 # l  u! C/ o- I6 t# ^% \% x
 $ `2 t: |2 T4 h$ R+ s* }输入mcc -W cpplib:youRFunLib -T link:lib yourfun.m
 : Z. z7 u: ?" [: G6 Z
 + I, W- a  p5 X) j其中,yourfunLib是生成的DLL,Lib的前缀名字,也就是你最后可以是使用的DLL以及Lib库的名字;yourfun是你需要编译的.m函数。
 + |4 B# c+ W8 ?# Y1 e0 b1 d; z5 `6 q! ?2 Z" _$ P1 O
 编译完成后得到了下图中的一些文件:
 ) o) |# s/ J2 O, k$ O* f- W* T& L1 E5 b; {6 R( R2 j& S0 @3 G
 
  5 m' y7 |  n7 s& ^ , P, K. {+ x' O4 E5 Y' P6 x% I  [
 这些文件中后缀为DLL,LIB,H的文件在VS调用的时候有用,其他文件目前没有使用。(这里我把yourfunLib指定为aetherLib了)
 9 }2 u# \# @! J" ^
 3 r: [8 o( v% U四,VS2010 的配置3 d  q, ^2 V& n5 L$ f6 b+ |- m+ U
 
 - z; [  }& [: `6 ^4 [4 _( t9 X" G新建一个控制台项目。
 % P0 `0 z4 ^2 ~+ T3 I1 k4 W. S# d4 S1 f' u
 打开项目的属性页,针对这个项目做如下的设置:3 w4 K7 t5 ~: `- L5 ?
 
 ( }' K  K5 Q! L% p1 W. R1.VC++目录下的包含目录添加! Z$ u1 W4 T& A2 g
 
 2 D/ b; W: [/ x4 k  k5 t& bD:\R2011a\extern\include(matlab安装目录下的路径)
 ; ?7 ^  `6 Y9 z8 K/ K
 6 ?: g5 E5 n6 ~9 o. yD:\R2011a\extern\include\win32  (matlab安装目录下的路径,下同)
 ( g6 C' t  L. R: O/ [( }8 Z( G* J# u: y; N9 J: R) a! J& U/ O; z
 C:\Users\lenovo\Desktop\aether\aether  (你自己新建的项目中的路径,下同)0 J+ ]" M* _, x. V4 ^, `  }: n7 W
 / p/ b8 `, R) W. o" J9 F
 2.VC++目录下的库目录添加
 * ^  z+ a: K7 j& d6 }1 c& _% N7 z- b! A; U1 P
 D:\R2011a\bin\win32
 L+ b0 E! O8 h) r9 s: a; e8 A& w/ g7 Z' ^# Y4 _0 @$ k* V2 ]( \
 D:\R2011a\extern\lib
 1 Z- E& u* y: l
 + `) ?$ s/ _! d8 H; M( Y8 nC:\Users\lenovo\Desktop\aether\aether( s: P( A* C3 X
 2 Q' \# w. ^; n: F! e4 J
 D:\R2011a\extern\lib\win64\microsoft( J: A5 k9 Z" W  ^$ i
 
 }0 N! r/ ^8 kD:\R2011a\extern\lib\win32\lcc
 ' p0 c+ Q" C% @7 l' |4 W2 c) Q& y# s) @% P4 @
 D:\R2011a\extern\lib\win32\microsoft1 Y- y5 q% B% ]7 H( s
 7 l: U3 x' C5 v+ k: v! K
 3.c/c++中的常规里面的附加包含目录添加
 T8 u( D+ d* G8 t' Q6 f" Y! T/ Z" H# r+ Y, I
 D:\R2011a\extern\include
 * w& Y+ ^! v5 Z, ]
 # o/ S- c9 k0 K( V3 Z+ e" B$ \4.连接器下面的常规中的附加库目录添加
 + C0 D/ ^# R  l/ {: S/ G4 ?: ]% Z' g. o" ]9 [) n0 r, Y6 `
 D:\R2011a\extern\lib\win32\microsoft
 ( B) d7 P5 _4 w& y! W. l1 y# k% B
 & |5 |$ X$ O# B; |# \5.连接器下面的输入中的附加依赖项添加% ^/ S" m! P" C' w- J$ ?
 2 _6 ~  e9 F& e
 libeng.lib
 , s4 `4 N8 M" z6 g& S
 1 @; j, F/ V5 Hlibmat.lib
 7 J4 |- J9 X6 @5 Q$ _. c: c' w
 ! C6 }( ?( t9 S' [, S5 x$ h# Alibmex.lib+ R3 c: k6 ^9 T( w
 $ t& F7 S$ @7 z- P
 libmx.lib& ~; J9 |. I* F1 o! k' r
 0 n5 {* q) Q* y' Q/ Z4 w4 k- b
 mclmcrrt.lib
 / e* T+ K3 e& s/ O+ H- g: w
 7 g5 g7 M1 o! ]* d6 ]/ ?9 amclmcr.lib1 ~  B2 m8 |/ I/ {- L
 
 " c0 n: v- C7 G' v! RaetherLib.lib(这个是你自己用matlab生成的lib,前面的是matlab自身计算引擎中的lib)
 b/ O. Y+ \& F5 ^% d0 p
 3 `) t  N6 ]+ q( m在解决方案资源管理其中的头文件和资源文件中添加文件7 r  x0 P( ?% @/ S% \: X- m
 / E+ O# \) M# {5 ~) H4 L
 1.在头文件中添加生成的.h文件
 3 c, E4 [5 g! x" A! b& R0 ^! D3 O" g8 q6 d
 2.在资源文件中添加.lib,.dll文件1 t1 ~4 h9 `# c) k. K$ b: R+ u
 * ^- K  O- y2 b1 e# l
 3.然后 把.h,.lib,.dll文件拷到你新建的项目的目录下。比如我把他们放到了C:\Users\lenovo\Desktop\aether\aether里面。
 . f3 T4 F: f) s7 b5 W. C8 ~1 t8 ]: R. d, W3 ]4 y
 (最好是用这个命令进行编译 mcc -W cpplib:MyAddLib -T link:lib MyAdd.m -C. j- T" W  K) m3 ~% F: X7 t
 8 G3 @2 ~) b: e+ o0 e# J
 然后把.ctf文件也拷过去。)- W5 U! u; _. z) Z  b6 V9 h; L2 _9 P
 ( z5 q: |3 m8 c, X3 ?$ F* D2 z
 编写代码调用dll中的函数/ }/ N# y9 j* M% }3 H9 o
 % Q1 R1 D" o9 T) u( h3 N* u1 [
 dll中的函数的接口形式在.h文件的最后面给出了,你可以去翻看他接口形式。这里面的函数的输入输出参数都得是mwArray对象的常引用,关于这个类请读者自己去网上搜索资料。你需要搞明白的是mwArray是matlab公司专门针对“c++调用matlab生成的dll“而设计的类,因为你包含了matlab安装目录下的这些类,所以你可以在VS里使用它们。6 A0 l$ q. T/ u: f* F) v* j
 
 . I. c' n& ~$ q6 G下面是一段主函数的编写样例:
 # f! N2 F* X9 o
 . r; z5 U/ {' Y; A+ J. h! J// newdll.cpp : 定义控制台应用程序的入口点。
 3 e/ o$ f8 O5 O7 [! Y4 J8 {4 C8 C- }+ z' y3 I
 //# z3 T4 L; o) ?* H
 9 R: \' v: b, A. A" O
 #include "stdafx.h"' x" I/ }+ d0 Y
 
 ( N& o/ Y8 |/ D9 [2 S) Z#include
 - C. v1 w6 s# a: O0 B# Q; `! y' T0 j' k7 U: s" |
 #include "engine.h"
 2 {' o  b4 i" ]! ~
 9 s' I" V/ T1 k  M' J  f8 f#include "mclmcr.h"
 ; r3 Q0 |* y' `* S
 ( R3 D) H  H& y3 K6 `#include "mclcppclass.h"
 . M- H; M, a, Z  x6 Q
 1 U' H$ P6 n/ W#include "libMyAdd.h"
 ! T8 N- ]" m  P. J: c0 d  P: Z
 - \% V" K1 @4 I1 }& z- pusing namespace std;$ p, J9 T- e0 L+ h  y4 t5 g
 
 $ Y) h# }- A& U& h) S' d4 a$ E# fint _tmain(int argc, _TCHAR* argv[])
 4 B5 \( |5 a# L" {) I3 o
 " y! A6 e% J. w' H" W" R' m{
 ; p+ x* P& ~# e1 G, N/ a
 $ W# E" D' f: Q. i3 F* z if(!libMyAddInitialize())
 . ~( F6 ]* c1 _1 v8 C' d% @  D' i8 w4 y5 a" o. ]/ v
 {
 / A8 }2 _2 g5 |9 S0 x, ^8 k3 C% H4 ^* I
 //initilize failed!!!"<<std::endl;& @8 C" S+ F& r
 
 # n# W' Y- p2 r' L  y% v$ D    std::cout<<"错误..."<<std::endl;1 A8 f  _, h7 c$ H  l. w
 
 , |& h, V" U; o6 }- R, A6 ^   return -1;, ]. t" N: X8 F
 
 o1 f& m* \, \   }0 l. U( k+ y  }( H) E# v
 
 6 H; g( U4 B2 i4 D0 ]: D0 e double a = 6;
 ! N: b+ `; e; J! C% F' L7 {) G* \! h0 L$ f, M3 \4 J" j
 double b = 9;4 }/ N8 i, Z( a0 F) t. o" \
 7 t) |  `. t- e5 {
 double c;( B' |3 Z" j. D' p+ T
 2 @/ l3 I: Z5 a8 N! _
 mwArray mwA(1, 1, mxDOUBLE_CLASS);
 + N$ v1 e3 U0 @0 h+ }8 @; o- C1 S- r. D
 mwArray mwB(1, 1, mxDOUBLE_CLASS);- q) m8 U" m( C8 N. c* O/ s- E
 5 M( ^! L+ E6 t% i
 mwArray mwC(1, 1, mxDOUBLE_CLASS);
 ( b7 E: z* t& M! ?3 I; u2 \
 & L- X- V9 I0 D; p- V8 d! nmwA.SetData(&a, 1);
 & T! u  t; d6 G
 ; L# c; \/ f2 u$ imwB.SetData(&b, 1);
 1 @4 W, k. I1 ^- U, u
 1 z' h% H# q1 }$ c* @1 U' [! [& d3 a6 pMyAdd(1, mwC, mwA, mwB);0 t1 i: A- y4 ~
 
 * y6 u$ d( Z$ y  Pc = mwC.Get(1,1);6 G# Y  r/ g% r" o) _
 
 / M  `8 C6 b2 `# P. T" Hcout<<c<<endl;' D+ |  O5 C( {0 ]9 {0 q! T
 
 7 o0 r1 Y+ y1 v: C$ t1 X0 ^$ Q% m* |! p, ksystem("PAUSE");
 ; |# ~8 d- M: X& K7 G% |2 d. Q" Z/ }" J7 ?7 b5 K, p3 _1 S: M
 return 0;! L- {3 I5 Z  Q
 ?. B$ ~0 y$ Q
 }
 % z5 w1 M( l( K; \( K) B# [- B: p1 B; E9 T, M2 Z
 这个dll中的函数只是实现了一个简单的两数相加的功能,是我做基本配置是使用的。
 / d$ c* u, {: ~; J, n" l; C2 w( B! h; x: h: b, n# g5 [$ W5 D- _1 D
 #include "engine.h"
 % a: {( H; ?- X& I3 w8 D# D+ r; Q6 |
 #include "mclmcr.h"% O( U. E, e% p) ?
 
 & ^. W6 Z* r, S0 C4 O#include "mclcppclass.h"
 8 t3 H5 l/ d) k5 W( O# o/ ~& r3 G) t( t
 #include "libMyAdd.h"       这些头文件是必须包含的,其中engine好像是包含了matlab计算引擎中的所有dll(还没有认真考证)$ L4 F5 w& i: m# x
 9 H% ]  O7 h$ t6 s1 Z4 z  ^
 现在,运气好的话你应该能看到你预想中的输出了。如果出现了问题,比如找不到路径,不可访问等等各种错误,那只能你自己去解决了,我搞了整整3天,上面提到的错误都有遇到。  出了错误你可以尝试去百度搜索其他博客,更好的是去google用英文搜索相关的问题,一些社区里面也许有答案呢,matlab版主文档我倒是没仔细看,也许上面也有不错的帮助呢! good luck  to you!2 h( n- f/ z3 M# t3 e7 E
 
 - @! @' d0 A, M- H9 P7 `, e1 z备注:3 M) V* [- F6 r! U5 o
 0 W8 p- G$ w4 ]
 1.我自己在搞的时候,遇到的问题是.m函数中本身就使用了c++语言编写的dll,然后再封装这个.m函数。这种情况下你得保证VS可以访问到你用到的那些用C++书写的dll。但是只要用mcc命令编译.m函数后,你在连接器下面的输入中的附加依赖项中只需添加.m 生成的dll函数就可以了,不需要添加那些c++代码生成的dll。这里建议你把matlab项目拷到VS项目中,直接在Vs项目中工作进行MCC编译。
 @- C4 U$ Q7 z) e% J$ z2 a6 b) h4 r2 |3 l6 d) |
 2.主函数代码中if(!libMyAddInitialize())是必须的。( g! n* T2 d+ ~
 
 . V: N4 l# U9 `( B- }- V4 w7 m
 | 
 |