【fishing-pan:https://blog.csdn.net/u013921430转载请注明出处】
前言
Matlab是一个非常强大的工具,为我们平时的学习和工作提供了非常大的便利。Matlab不仅自身功能强大,还为其他语言提供了接口,早前的学习中需要用的C++读写.mat文件,今天将当时的学习心得分享给大家,希望对大家有所帮助。
软件工具:VS2013+Matlab2016a+Win7(X64)
工程配置
1. 添加环境变量
因为要用到Matlab的自带的库,所以需要将Matlab中库所在的目录添加到环境变量中
将以下路径添加到环境变量中
F:\matlab2016a_exe\extern\lib\win64
F:\matlab2016a_exe\extern\lib\win64\microsoft
然后重启电脑(路径根据你的安装路径有所调整)
2.创建VS项目并配置管理器
在创建一个VS新项目后,默认是win32的项目,但是由于我的Matlab是x64的,所以需要重新配置管理器;
点击配置管理器,然后再在弹框中选择新建,最后选择x64即可;
3. 项目属性
右键项目,在弹出的最后一项中选择属性,
选择 C/C++ ——>常规——>附加包含目录
输入以下路径,点击确定按钮
再下滑选择链接器——>常规——>附加库包含目录
输入以下路径
点击确定,然后下滑选择输入——>附加依赖项
输入以下四个库:
- libmat.lib
- libmx.lib
- libmex.lib
- libeng.lib
最后点击确定
编写代码
为了方便展示,在此先将C++代码展示给大家,方便后续的展开讲解;
代码
#include <mat.h>
#include <iostream>
using namespace std;
double mat_read(string path, string name, mxArray *&Array1, mxArray *&Array2)
{
MATFile *pmatFile = matOpen((path + "\\" + name + ".mat").c_str(), "r");
if (pmatFile == NULL)
cout << "MatOpen error!!!" << endl;
Array1 = matGetVariable(pmatFile, "length");
Array2 = matGetVariable(pmatFile, "tracts");
matClose(pmatFile);
return 0;
}
int main()
{
mxArray *Array1 = NULL;
mxArray *Array2 = NULL;
string filepath = "G:\\博客\\C++获取mat数据\\CPPgetMat\\CPPgetMat";
string filename = "InputTest";
mat_read(filepath, filename, Array1, Array2);
int64_T *dim = (int64_T *)(mxGetDimensions(Array1));
//int *Dim = (int*)dim;
int ss = mxGetNumberOfDimensions(Array1);
int pp = mxGetM(Array1);
cout <<"数据有"<< ss << "维度"<<endl;
for (int i = 0; i < ss;i++)
{
cout << "第" << (i + 1) << "维度的大小是" << dim[i] << endl;
}
double *Data = (double*)mxGetData(Array1);
cout <<"Data[0]的值是"<< Data[0] << endl;
double *out = new double[6];
for (int i = 0; i < 2;i++)
{
for (int j = 0; j < 3; j++)
{
out[i*3+j] = 5 * j + i;
}
}
MATFile *OutFile = NULL;
mxArray *pMxArray = NULL;
OutFile = matOpen("G:\\博客\\C++获取mat数据\\CPPgetMat\\CPPgetMat\\outTest.mat", "w");
pMxArray = mxCreateDoubleMatrix(2, 3, mxREAL);
//mxSetData(pMxArray, (mxArray *)out);
memcpy((void *)(mxGetPr(pMxArray)), (void *)out, sizeof(double)*6);
Data = (double*)mxGetData(pMxArray);
//cout << Data[4] << endl;
matPutVariable(OutFile, "test", pMxArray);
system("pause");
return 0;
}
输出
输出结果
输出数据
我们来看看读入的数据,
数据中有两个数据成员变量length和tracts;
变量length的内容为
代码分析
读入mat文件的代码分析
1. 使用matOpen函数打开mat文件
MATFile *matOpen(const char *filename,const char *mode)
filename:文件路径和名称(.mat文件)
mode:打开文件的三种模式
r:以只读方式打开
u:更新模式,可读可写,但是如果要打开的数据文件不存在,也不会创建新的文件
w:以写入方式打开,只能写如入,如果要打开的数据文件不存在,则创建一个新的文件;
2. 使用matGetVariable函数读取mat文件中的变量
mxArray * matGetVariable(MATFile * pMF, const char *name);
读取名为name的变量,返回一个数据阵列指针
pMF:指向所读入的文件的指针;
name:文件中名为name的变量,该变量必须是已存在的;
3. 使用mxGetDimensions获取数据维度
const size_t *mxGetDimensions(const mxArray *pa);
获取数据的各个维度的大小并返回的维度保存在一个数组中;
此外还可以使用mxGetM和mxGetN函数获取数据阵列矩阵的维数
size_t mxGetM(const mxArray *pa);
第一维,也就是矩阵有多少行
size_t mxGetN(const mxArray *pa);
第二维,也就是矩阵有多少列,若是多维数组,则返回其他所有维度的乘积。
4. 使用mxGetData函数获取数据阵列中的数据
void *mxGetData(const mxArray *pa );
由于返回值是void的,所以需要进行强制的返回类型说明,返回类型根据Matlab中变量存储的类型确定。
注意:无论mat的维度是多少,在C++中均是1维的数据,并且数组的第一个编号是1,所以在赋值给新数组时候,需要减去1;
从上面的输出结果看出,C++中的第一个元素编号是0,而在Matlab中第一个元素的编号是1;所以Data[0]=40;
5. 使用mxGetNumberOfDimensions获取维度数量
返回维度的数量,比如length的维度数量为2;int mxGetNumberOfDimensions(const mxArray *array_ptr);
写出.mat文件的代码分析
1. 使用matOpen函数打开mat文件
见上文
2. 使用mxCreateDoubleMatrix创建数组
mxArray *mxCreateDoubleMatrix(size_t m, size_t n, mxComplexity flag);
创建一个m行,n列的数组,flag处一般填写mxReal即可,表示是实数,还可以填写mxCOMPLEX;
3. 使用memcpy进行数值拷贝
在早前版本的matlab自带的版本中使用的是mxSetData函数进行数值输入,但是在比较新的版本中,这个函数使用会出现错误,笔者也不知道为什么。所以在不确定的情况下,你可以使用memcpy;
//mxSetData(pMxArray, (mxArray *)out);
memcpy((void *)(mxGetPr(pMxArray)), (void *)out, sizeof(double)*6);
同读出数据一样,写入数据也需要注意以下问题
注意:输入的数组out必须是1维的,而且Matlab是按列存储的,这与C++中按照行存储不同,所以我们原本输出应该是
0,5,10;1,6,11;却变成了我们所看到的结果中的0,10,6;5,1,11;
有疑问的可以尝试使用Matlab中的reshape函数;
4. 使用matPutVariable将变量放入文件中
matError matPutVariable(MATFile * pMF, const char * name, const mxArray * pA);
pMF:指向所读入的文件的指针;
name:文件中名为name的变量,若该变量名已存在的,则会被覆盖;
pA:被写入的变量;
如果写入成功则会返回0,如果写入失败则返回非0;
5. 关于内存释放
有的博客中写到完成mat文件操作后需要调用matClose函数关闭文件,并使用mxFree释放内存
但是,笔者在写入数据后,尝试使用matClose函数关闭被打开的文件和使用mxFree函数释放内存时,出现了释放内存的错误,这可能是版本不同的原因,读者按照自己的Matlab版本酌情处理。
本博客撰写参考了以下博客,特说明,深表感谢;
http://blog.csdn.net/left_la/article/details/8206645