Matlab 和 C/C++混合编程

说明:
这篇博文是对下面两边博文进行总结和整理,以及补充。

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"
void   timeST wo(double y[], double x[])
{  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) 
     mexErrMsgTxt("Too many output  arguments");
 
% 获取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+
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值