说明:
这篇博文是对下面两边博文进行总结和整理,以及补充。
1. Motivation
Matlab 擅长于矩阵运算,含有数据分析处理、系统分析、图形等工具包,但程序运行较慢;而C++高效的处理循环,属于低层语言和硬件比价接近,运行效率高。通过Matlab和C/C++混合编程可以集两者之长。
2. 混合编程的情况可以分为下面几种情况
Case:(A) 使用Matlab 调用C++
(i) 利用MEX将C/C++编译为Matlab executable file ,如 fun.mexw64 (MEX 编译)
(ii) 直接调用C/C++ 动态链接库 (利用Matlab API)
Case:(B)C/C++ 调用Matlab
(i) 利用Matlab 计算引擎
(ii)利用Matlab 自带的c++ compiler(mcc)生成cpp、hpp文件(依赖于matlab的C/C++ API,lib文件)
(iii)利用Matlab 自带的c++ compiler(mcc)生成 DLL文件(完全脱离matlab运行环境)
3. Case A: 使用Matlab 调用C++
(i) Matlab 调用C++ MEX文件
Matlab 和VS 环境设置
Matlab : Mex 编译器设置: mex -setup , 选择和生成C/C++代码运行平台一致的编译器,如VS2010的编译器
VS设置:
(在Matlab运行环境下进行,不需要设置VS)
一个
C/C++
的
MEX
源程序通常包括
4
个组成部分
,其中前
3
个是必须包含的内容,第
4
个则根据所实现的功能灵活选用
:
(1) #include“mex.h”;(2) MEX文件的入口函数mexFunction, MEX文件导出名必须为mexFunction函数;
(3 mxArray
(4) API函数
注: (i) 将C/Cpp 文件编译为matlab可以执行的程序,关键是“数据格式的转换”。Matlab中使用的是矩阵类型,一个标量也是使用矩阵进行表述的;而C/CPP中使用的初级类型是int,double等。如何将两类数据调整一致是一个基本问题。
mxArray使用C定义的一个数据结构。matrix(in matlab) 与 mxArray由matlab进行完成,而mxArray 和C/C++基本数据类型之间的转换由用户利用matlab提供的接口函数进行转换。mxArray 是一个数据结构(结构体),matlab的接口中定义了非常多的函数对这个结构体进行操作,用于数据交换。mexFunction()的声明在mex.h中(mex.h文件包含了大部分数据交换的需要的函数)
定义使用mex的目的是为了利用现有的C/C++代码,不用重新使用matlab实现,或利用其高效性。生成的*.mex64w文件会在matlab中被调用,传入的参数是matlab中定义的矩阵,传出的参数也是matlab中定义的矩阵。
User在C/C++文件中对定义功能,并且接口的数据结构严格依照Matlab的规定,传入传出参数都是mxArray。
(i)先将传入的
mxArray参数,利用Matlab提供的
API函数转成C/C++数据,如 int mrow = mxGetM(mxArray* p) , double* p = mxGetPr(prhs[0]).
(ii)在
mexFunction中调用C/C++function ,得到C/C++中类型数据。
(ii)将得到的C/C++数据转成mxArray数据结构传出。
mex编译器负责将这样的“八股文”翻译成为matlab可以执行的二进制文件。
注: void指针是没有意义的,double指针表示指针的移位按照sizeof(double)个字节进行。
Example:
#include "mex.h"
{ y[0] = 2.0*x[0]; }
void
mexFunction(
int nlhs, mxArray * plhs[], int nrhs, const mxArray *prhs[]
)
{
double *x,*y;int mrows, ncols;
if( nrhs!=1)mexErrMsgTxt("One input required.");else if( nlhs>1)% 获取mxArray的信息,用作C/C++函数的输入mrows = mxGetM ( prhs[0] );ncols = mxGetN(prhs[0]);
if( ! mxIsDouble (prhs[0]) || mxIsComplex ( prhs[0] ) || !( mrows ==1 && ncols==1 ) )mexErrMsgTxt( "Input must be a noncomplex scalar double." );
plhs[0] = mxCreateDoubleMatrix ( mrows, ncols, mxREAL );x = mxGetPr( prhs[0] );y = mxGetPr( plhs[0] );
% 调用C/C++函数% 输出值x 通过double指针存入输入指针prhs[0]所指的区域timestwo(y,x);
}
(ii) Matlab 调用C++ 动态链接库
利用该接口,可在
Matlab
中调用动态连接库导出的函数。
Matlab
对
DLL
的接口
支持各种语言编写的
DLL
文件
。在调用
DLL
文件之
前,需要准备函数定义的头文件。对于
C/C++
语言开发的
DLL
文件,可使用源程序中相应的
头文件;而对于其他语言开发的
DLL
,则要手工准备等效的
C
语言函数定义头文件。
在
Matlab
中利用动态连接库接口技术通常需要完成以下
4
个步骤:
(1)
打开动态连接库文件;
(2) 为调用函数准备数据;
(3) 调用动态连接库文件中导出的 函数;
(4)
关闭动态连接库文件。
为了实现以上步骤,用到的
Matlab
函数有:
loadlibrary, calllib, libfunctions, libpointer, libstruct, libisloaded
。
C++编写.cpp,.h文件并且shengcheng .dll,.lib,.h文件。
Example:
-----------------------------------------------------------------------
#include "a.h"
_declspec(dllexport) int add( int a , int b)
{return a + b ; }
编译生成Test1.dll, Test1.lid, Test1.h
----------------------------------------------------------------------
Matlab 命令行下:
loadlibrary('Test1') % 打开动态链接库
x = 7 ; y = 8 ; % 准备数据
calllib('Test1', 'add', x, y) ; % 调用动态链接库导出函数
unloadlibrary('Test1' ) ; % 关闭动态链接库
调用
DLL
动态连接库的方法,为
Matlab
重用工程实践中积累的大量实用
C/C++
代码提供了一种简洁方便的方法。与调用
MEX
文件相比,该方法更加简便实用。但是这个接口之支持
C,不支持C++
库和函数的重载,这种情况下,推荐用
MEX-file
,若实在要用这种方法(
调用C/C++动态连接库
),则对于
C++
要做一些更改,详见
http://www.mathworks.de/help/techdoc/matlab_external/f43202.html#bq__4nu-1
,
4. Case B: C+