概述
说了c++,其实实质上是matlab与c的混合编程。因为matlab提供的东西几个函数就能搞定了,不必要动辄用到C++的特性。matlab与c交互有几种方式,我认为可分为两类:一类是c从matlab里取东西,一类是matlab从c里取东西。这两类的内容在matlab的User’s Guide里都有,在C/C++ and Fortran API Reference中。
我今天将要在c中将数组数据放到matlab矩阵类型中,并将这些矩阵写入mat数据文件。用到的功能在matlab的MAT-File Library和MX Matrix Library中,这两个功能的函数分别在/MATLAB/R2010b/bin/win32/libmat.dll和/MATLAB/R2010b/bin/win32/libmx.dll中。对应的头文件为/MATLAB/R2010b/extern/include/mat.h和/MATLAB/R2010b/extern/include/matrix.h,对应lib文件为/MATLAB/R2010b/extern/lib/win32/microsoft/libmat.lib和/MATLAB/R2010b/extern/lib/win32/microsoft/libmx.lib。上面说的都是在vs系列编译环境中需要的,有了这些我们就可以安安稳稳的使用matlab提供的这些API了。
下面的文章清楚的说明了如何使用matlab提供的函数生成mxArray矩阵以及将矩阵放在mat文件中http://www.mathworks.com/help/techdoc/matlab_external/f39876.html。并且这里还有一个例子用来很好的说明问题,也可以用来测试编译环境是否已经配好http://www.mathworks.com/help/techdoc/matlab_external/rmvd_matlablink__33.html。
然后就是我简单总结一下整个过程。整个过程在一段完整的代码上进行讲述。
1: int main()
2: {
3: MATFile *pmat;
4: mxArray *pa1, *pa2, *pa3;
5: double data[9] = { 1.0, 4.0, 7.0, 2.0, 5.0, 8.0, 3.0, 6.0, 9.0 };
6: const char *file = "mattest.mat";
7: char str[BUFSIZE];
8: int status;
9:
10: printf("Creating file %s.../n/n", file);
11: pmat = matOpen(file, "w");
12: if (pmat == NULL)
13: {
14: printf("Error creating file %s/n", file);
15: printf("(Do you have write permission in this directory?)/n");
16: return(EXIT_FAILURE);
17: }
18:
19: pa1 = mxCreateDoubleMatrix(3,3,mxREAL);
20: if (pa1 == NULL)
21: {
22: printf("%s : Out of memory on line %d/n", __FILE__, __LINE__);
23: printf("Unable to create mxArray./n");
24: return(EXIT_FAILURE);
25: }
26:
27: pa2 = mxCreateDoubleMatrix(3,3,mxREAL);
28: if (pa2 == NULL)
29: {
30: printf("%s : Out of memory on line %d/n", __FILE__, __LINE__);
31: printf("Unable to create mxArray./n");
32: return(EXIT_FAILURE);
33: }
34: memcpy((void *)(mxGetPr(pa2)), (void *)data, sizeof(data));
35: int k=0;
36: double* temp;
37: temp=(double*)mxGetData(pa2);
38: for(k=0;k<6;k++){
39: temp++;
40: }
41:
42: pa3 = mxCreateString("MATLAB: the language of technical computing");
43: if (pa3 == NULL)
44: {
45: printf("%s : Out of memory on line %d/n", __FILE__, __LINE__);
46: printf("Unable to create string mxArray./n");
47: return(EXIT_FAILURE);
48: }
49:
50: status = matPutVariable(pmat, "LocalDouble", pa1);
51: if (status != 0)
52: {
53: printf("%s : Error using matPutVariable on line %d/n", __FILE__, __LINE__);
54: return(EXIT_FAILURE);
55: }
56:
57: status = matPutVariableAsGlobal(pmat, "GlobalDouble", pa2);
58: if (status != 0)
59: {
60: printf("Error using matPutVariableAsGlobal/n");
61: return(EXIT_FAILURE);
62: }
63:
64: status = matPutVariable(pmat, "LocalString", pa3);
65: if (status != 0)
66: {
67: printf("%s : Error using matPutVariable on line %d/n", __FILE__, __LINE__);
68: return(EXIT_FAILURE);
69: }
70:
71: /*
72: * Ooops! we need to copy data before writing the array. (Well,
73: * ok, this was really intentional.) This demonstrates that
74: * matPutVariable will overwrite an existing array in a MAT-file.
75: */
76: memcpy((void *)(mxGetPr(pa1)), (void *)data, sizeof(data));
77: status = matPutVariable(pmat, "LocalDouble", pa1);
78: if (status != 0)
79: {
80: printf("%s : Error using matPutVariable on line %d/n", __FILE__, __LINE__);
81: return(EXIT_FAILURE);
82: }
83:
84: /* clean up */
85: mxDestroyArray(pa1);
86: mxDestroyArray(pa2);
87: mxDestroyArray(pa3);
88:
89: if (matClose(pmat) != 0)
90: {
91: printf("Error closing file %s/n",file);
92: return(EXIT_FAILURE);
93: }
94:
95: /*
96: * Re-open file and verify its contents with matGetVariable
97: */
98: pmat = matOpen(file, "r");
99: if (pmat == NULL)
100: {
101: printf("Error reopening file %s/n", file);
102: return(EXIT_FAILURE);
103: }
104:
105: /*
106: * Read in each array we just wrote
107: */
108: pa1 = matGetVariable(pmat, "LocalDouble");
109: if (pa1 == NULL)
110: {
111: printf("Error reading existing matrix LocalDouble/n");
112: return(EXIT_FAILURE);
113: }
114: if (mxGetNumberOfDimensions(pa1) != 2)
115: {
116: printf("Error saving matrix: result does not have two dimensions/n");
117: return(EXIT_FAILURE);
118: }
119:
120: pa2 = matGetVariable(pmat, "GlobalDouble");
121: if (pa2 == NULL)
122: {
123: printf("Error reading existing matrix GlobalDouble/n");
124: return(EXIT_FAILURE);
125: }
126: if (!(mxIsFromGlobalWS(pa2)))
127: {
128: printf("Error saving global matrix: result is not global/n");
129: return(EXIT_FAILURE);
130: }
131:
132: pa3 = matGetVariable(pmat, "LocalString");
133: if (pa3 == NULL)
134: {
135: printf("Error reading existing matrix LocalString/n");
136: return(EXIT_FAILURE);
137: }
138:
139: status = mxGetString(pa3, str, sizeof(str));
140: if(status != 0)
141: {
142: printf("Not enough space. String is truncated.");
143: return(EXIT_FAILURE);
144: }
145: if (strcmp(str, "MATLAB: the language of technical computing"))
146: {
147: printf("Error saving string: result has incorrect contents/n");
148: return(EXIT_FAILURE);
149: }
150:
151: /* clean up before exit */
152: mxDestroyArray(pa1);
153: mxDestroyArray(pa2);
154: mxDestroyArray(pa3);
155:
156: if (matClose(pmat) != 0)
157: {
158: printf("Error closing file %s/n",file);
159: return(EXIT_FAILURE);
160: }
161: printf("Done/n");
162: return(EXIT_SUCCESS);
163: }
一、创建mxArray矩阵变量。
1: double data[9] = { 1.0, 4.0, 7.0, 2.0, 5.0, 8.0, 3.0, 6.0, 9.0 };
2: mxArray *pa2;
3: pa2 = mxCreateDoubleMatrix(3,3,mxREAL);
4: memcpy((void *)(mxGetPr(pa2)), (void *)data, sizeof(data));
这段代码是从完整代中截取的,内容为创建mxArray矩阵,并将c格式的数据(必须为double类型的数组)放到mxArray矩阵中,主要用到了函数mxCreateDoubleMatrix()。这段代码使用这个函数创建了一个3*3的实数密集矩阵(相对于稀疏矩阵),并将矩阵的首地址赋给pa2(注:矩阵中元素默认初始值为0,类型相当于c中的double)。然后使用mxGetPr()找到这个矩阵的数据部分,再使用c的memcpy函数将原始数据拷贝到这块内存空间中。使用memcpy要小心点,这直接对内存的操作最容易出问题了。这里还有一个需要注意的地方,就是用memcpy将整块内存中的数据拷到mxArray中后,这个mxArray矩阵也就是在matlab中的矩阵按列优先排列数据。为了表述清晰,我画个图给大家看看。
二、将mxArray矩阵变量放到mat数据文件中。
1: const char *file = "mattest.mat";
2: MATFile *pmat;
3: pmat = matOpen(file, "w");
4: int status;
5: status = matPutVariableAsGlobal(pmat, "GlobalDouble", pa2);
程序先要创建一个MATFile结构,这个结构存储了关于mat文件的信息。使用matOpen命令打开指定的mat文件,若参数为"w”则为写,即可以通过pmat变量向文件里写东西。若使用matOpen命令打开的mat文件不存在,则新建此文件。有了mat文件的框框,接下来就是要往文件里写东西了。matPutVariableAsGlobal()和matPutVariable()命令差不多,具体差别还没研究,到时候再说,本文使用它们并没有什么区别。matPutVariableAsGlobal函数将pa2这个c中的mxArray结构用GlobalDouble的变量名写进了pmat指向的mattest.mat文件,即当我们在matlab中加载mattest.mat这个文件时,全局工作区中会出现GlobalDouble这个变量。mat文件中就有一个数据了,我们可以再向其中写入矩阵数据。这里需要提醒大家的是,如果写入的变量名在mat文件中已经存在,则新的变量会覆盖原来老的变量,这个同matlab中的情况一样,所以大家要小心。
三、处理后事。
1: mxDestroyArray(pa2);
2: matClose(pmat);
当然我们不能用完了mat文件就拍屁股走人了,还有善一下后的。mxDestroyArray函数释放刚才mxCreateDoubleMatrix申请的空间。matClose则负责关闭刚才打开的mat文件。这样就可以了。
以上这些就是整个的处理过程,但三步中引用的代码都是极为简单的,实际中还要加入一些判断条件,以免产生错误。如mxCreateDoubleMatrix可能没申请到空间,matOpen可能打不开文件等。剩下的大家就自己看上面给出的文章领悟吧,希望大家都能早日大彻大悟。
参考文献:
[1] http://www.mathworks.com/help/techdoc/matlab_external/f39876.html
[2] http://www.mathworks.com/help/techdoc/matlab_external/f14500.html
[3] http://www.mathworks.com/matlabcentral/answers/2973-visual-studio-2010-and-mat-files
[4] http://www.cnblogs.com/strinkbug/archive/2007/04/24/725050.html
[5] http://hi.baidu.com/ruoxinjiu/blog/item/d11c3e1b073426ddad6e75af.html
最后
以上就是糊涂小熊猫为你收集整理的matlab与c(c++)混合编程的全部内容,希望文章能够帮你解决matlab与c(c++)混合编程所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复