封装c++与matlab引擎交互的数据结构:行优先矩阵类
来源:互联网 发布:战地4龙之谷灯笼算法 编辑:程序博客网 时间:2024/06/16 18:22
我们知道matlab中的矩阵是列优先存储的,而c++中的数据是行优先存储的,而习惯了使用c++的伙伴们,也习惯了行优先存储方式了啦(比如看一个二维数组,总会先看行序号,再看列序号)。所以在进行c++调用matlab引擎处理时,这会给两者矩阵数据传递会带来诸多的烦恼,这也是诸多程序bug的来源之一。关于c++调用matlab引擎编程,可参考我的另一篇文,网址为http://blog.csdn.net/feichizhongwu888/article/details/47277565。
下面举一个例子,说明c++的数据存储顺序和matlab的存储数据方式。
int main(){ //c++ matrix:2*5=10 elements double a[10] = {0,1,2,3,4,5,6,7,8,9}; Engine* ep; if(!(ep = engOpen(NULL))) { std::cout<<"can't start Matlab Engine!!"<<std::endl; return EXIT_FAILURE; } engSetVisible(ep, true);
//generating matlab matrix::aa mxArray *aa = mxCreateDoubleMatrix(2, 5, mxREAL); memcpy(mxGetPr(aa), a, 10 * sizeof(double)); engPutVariable(ep, "aa", aa); std::cin.get(); engEvalString(ep, "clear;"); mxDestroyArray(aa); engClose(ep); return 0;}c++中有一个2*5的矩阵,总共10个元素,存储在a[10]里面,如代码所示,之后,将a[10]元素全部传递给matlab变量aa,我们希望matlab能构造一个矩阵:第一行为{0,1,2,3,4}第二行为{5,6,7,8,9},但事实并非如此。程序输出结果,在matlab command window测试aa的值为:
你会发现0-9个元素,是纵向依次填充到2*5的matlab矩阵当中的,这是说明了matlab是列优先存储。
因此,如果你希望matlab构造你理想的矩阵,就必须在c++中就把所有矩阵数据,按照列存储方式,放在一个一维数组里面,再传输给matlab引擎。比如以上例子,你需要把a写成{0,5,1,6,2,7,3,8,4,9},实际上就是将a转置,在按行存储在c++一维数组里面,感兴趣的伙伴可以用手写写,再推敲推敲。(反正这个还是挺拗人的,尤其对我这种长久以来习惯行存储的人来说。)
看到这里,你也许会发现,如果我要操作1万*1万个元素的矩阵,万一哪一个元素给填错了,那该是多么凄惨的事情,就注定你的程序在matlab调用这块就会卡顿很久。因此呢,我于是想出一个办法,封装一个行优先的矩阵类TMatrix,而类内部是按照列优先存储的,哈哈,这就解决了这个问题。对于用户来讲,使用TMatrix来存放数据可以继续按照行优先方式赋值;另外一方面,底层维护的数据指针已经是列存储方式的了,就可以直接传送给matlab生成理想的矩阵了。
接下来,就要介绍一下TMatrix的原理和简单的使用了。
(1)TMatrix的原理
1.对于外界用户,继续按照行优先逻辑,存入和提取数据,类似二维数组。
2.底层维护一个数据指针,对于外界传入的数据,先进行转置,之后再放入这个指针指向的数据空间。
以下为TMatrix类的基本接口:
定义:理想的矩阵:表示正确的矩阵,我们想要的矩阵。
template<class DataType>class TMatrix{public: TMatrix(); TMatrix(int _row, int _column); TMatrix(int _row, int _column, DataType* _pMatrix_); ~TMatrix();public: void set_size(int _row, int _column); DataType* data_ptr() { return this->pMatrix_; } //user cognitive row and column int row() { return this->column_; } int column() { return this->row_; } int length() { return this->row_ * this->column_ * sizeof(DataType); } int size() { return this->row_ * this->column_; } bool set_value(int _index_r, int _index_c, DataType _value); DataType get_value(int _index_r, int _index_c); void print();private: int row_; int column_; DataType* pMatrix_;};
第一个构造函数
TMatrix();需要和
void set_size(int _row, int _column);一起使用,否则,数据空间为空。详细可见源码实现。
第二个构造函数
TMatrix(int _row, int _column);直接可得到一定_row*_column的数据空间,初值为0。
第三个构造函数
TMatrix(int _row, int _column, DataType* _pMatrix_);设计目的:从matlab获取变量到c++中,得到的数据是列存储的,我们就可以使用这个返回的数据指针来构造一个TMatrix对象。通过行优先存储的方式方便得访问TMatrix,进而准确地访问matlab返回的矩阵。这点,后面例子会说明,实际证明很好用。
函数
void set_size(int _row, int _column);可以重新设置TMatrix对象的行和列的长度,底层会重新构造一个新的数据空间。
函数
DataType* data_ptr() { return this->pMatrix_; }很重要,返回指向底层数据空间的指针,按照我们理想的矩阵的列存储方式存储。返回的指针可通过mencpy函数将空间的数据拷贝到matlab的mxArray空间。
函数
int row() { return this->column_; } int column() { return this->row_; }各自返回,用户认为的矩阵的行和列数(即为理想的矩阵的行数和列数目)。
函数
int length() { return this->row_ * this->column_ * sizeof(DataType); } int size() { return this->row_ * this->column_; }各自返回,数据空间的占用大小和数据空间的全部元素数目。
函数
bool set_value(int _index_r, int _index_c, DataType _value); DataType get_value(int _index_r, int _index_c);是给TMatrix的数据存入数据,或取出数据。其中(_index_r,_index_c)表示一个元素的所在位置坐标,该位置为在理想的矩阵中的位置。
函数
void print();为输出基本的TMatrix信息,用于方便查看。输出矩阵为理想的矩阵排列。
测试源代码:
int main(){ Engine* ep; if(!(ep = engOpen(NULL))) { std::cout<<"can't start Matlab Engine!!"<<std::endl; return EXIT_FAILURE; } engSetVisible(ep, true); const int row = 6; const int column = 10; //TEST 1: TMatrix Initialization CG::TMatrix<double> mat1(row, column); int k = 1; for(int i = 0; i < row; i++) { for(int j = 0; j < column; j++) { mat1.set_value(i, j, k++); } } std::cout<<"Test 1: orgin data: "<<std::endl; mat1.print(); //TEST 2: mxArray *aa = mxCreateDoubleMatrix(row, column, mxREAL); //get mat2.data_ptr() and transmit column-priority data to matlab workspace memcpy(mxGetPr(aa), mat1.data_ptr(), mat1.length()); engPutVariable(ep, "aa", aa); std::cout<<"Test 2: aa, see Matlab command window"<<std::endl; //TEST 3: mxArray* xx = engGetVariable(ep, "aa"); //get matrix from matlab workspace,then structure a row-priority TMatrix CG::TMatrix<double> mat2(mxGetM(xx), mxGetN(xx), mxGetPr(xx)); std::cout<<"Test 3: data from matlab workspace: "<<std::endl; mat2.print(); //TEST 4:access TMatrix for(int i = 0; i < row; i++) { for(int j = 0; j < column; j++) { std::cout<<mat2.get_value(i, j)<<" "; } std::cout<<std::endl; } //END std::cin.get(); engEvalString(ep, "clear;"); mxDestroyArray(aa); mxDestroyArray(xx); engClose(ep); return 0;}
这边做了4个测试:
Test1:TMatrix对象mat按行优先初始化,并输出。
Test2:TMatrix数据拷贝给matlab矩阵aa,并在Matlab command window中查看aa的输出值。
Test3:从Matlab 空间获取变量aa的值,保存至新的mat2,并输出。
Test4: 按行优先初始化访问mat2的值。
测试输出结果如下:
Test1 - Test4输出窗口,其中Test2测试结果参考下图。
从结果上可以发现,Test1 -- Test4的所有结果都是一样的。
结论:通过TMatrix类,可实现完全的行优先数据存储,行优先访问,完全满足c++与matlab引擎交互的需要。
希望对大家有帮助。
- 封装c++与matlab引擎交互的数据结构:行优先矩阵类
- Matlab与数据结构 -- 求向量或矩阵的最大值
- 与引擎简单的交互!
- matlab中的矩阵是行优先还是列优先?
- MATLAB与word的交互
- 【MATLAB与C的混合编程】之【C程序调用Matlab计算引擎】(1)
- 封装类DataProtocol 实现后台与页面的数据交互
- V8引擎与GUI间的交互
- Matlab与数据结构 -- 搜索向量或矩阵中非零元素的位置
- C用面向对象的方法封装矩阵类
- jQuery的Cookie封装,与PHP交互
- C++与Matlab混合编程之:矩阵数据结构
- 基于COM组件的MATLAB R2009a与C#.NET2010的交互编程
- 3D游戏引擎底层数据结构的封装之Array
- 3D游戏引擎底层数据结构的封装之Dictionary
- 3D游戏引擎底层数据结构的封装之List
- 3D游戏引擎底层数据结构的封装之Queue
- 3D游戏引擎底层数据结构的封装之Stack
- FDB Flash Debugger 远程调试页面FLASH
- java.sql.SQLException: ORA-00604: 递归 SQL 级别 1 出现错误
- 布卡漫画加载进度条
- window中使用memcache攻略(应用语言:PHP)
- 点两下退出
- 封装c++与matlab引擎交互的数据结构:行优先矩阵类
- leetcode:Integer to Roman
- 一个简单了解spring的例子
- 【小结】最小费用流&最大权闭合图
- Bitmap.createBitmap函数有6个重载方法
- Android Service把值传给Activity
- OpenWrt创建新用户
- python 的日志logging模块
- Win8 64位系统最简单的adb安装方法