Matlab external Interface这玩意的中文不知道是什么,感觉是Matlab插件一类的东西。我用c++写了一个函数可以生成一个巨大的矩阵。但是这个矩阵的svd分解我可不想再用c++写了。于是我想把这个大矩阵导入matlab的*.mat文件中,让matlab的svd命令来计算这个矩阵的svd分解。Matlab external Interface允许我写一个可以生成matlab Mat文件的c++程序。当然要包含matlab的头文件 "mat.h",同时还要与matlab的*.so(linux) *.lib(win32)等库文件链接。可执行文件的编译和链接功能可以有mex命令自动实现,不用自己写Makefile。我自己尝试写一个makefile但是没有编译成功。先贴出我的代码在细讲吧:
1 #include <stdio.h>
2 #include <string.h> /* For strcmp() */
3 #include <stdlib.h> /* For EXIT_FAILURE, EXIT_SUCCESS */
4 #include <vector> /* For STL */
5 #include <iostream>
6 #include <fstream>
7 #include "mat.h"
8
9 using namespace std;
10
11 #define BUFSIZE 256
12
13 int main() {
14 MATFile *pmat;
15 mxArray *pa1;// *pa2, *pa3;
16 fstream infile("outputMat", ios::in);
17 if( ! infile.is_open() )
18 {
19 cout << "no file" << endl;
20 return -1;
21 }
22 std::vector<int> myInts;
23 myInts.push_back(1);
24 myInts.push_back(2);
25 printf("Accessing a STL vector: %d\n", myInts[1]);
26
27 //double data[9] = { 1.0, 4.0, 7.0, 2.0, 5.0, 8.0, 3.0, 6.0, 9.0 };
28 double *data = NULL;
29 const char *file = "mattest.mat";
30 char str[BUFSIZE];
31 int status;
32 int width,height;
33 infile >> height;
34 infile >> width;
35 cout << height;
36 data = (double*)malloc(sizeof(double)*width*height);
37 if( !data )
38 {
39 cout << "Out of Memory !" << endl;
40 return -1;
41 }
42 for(unsigned i = 0; i < width * height; i++)
43 {
44 float tmp;
45 infile >> tmp;
46 data[i] = (double)tmp;
47 //cout << data[i] << " ";
48 }
49 infile.close();
50
51 printf("Creating file %s...\n\n", file);
52 pmat = matOpen(file, "w");
53 if (pmat == NULL) {
54 printf("Error creating file %s\n", file);
55 printf("(Do you have write permission in this directory?)\n");
56 return(EXIT_FAILURE);
57 }
58
59 pa1 = mxCreateDoubleMatrix(width,height,mxREAL);
60 if (pa1 == NULL) {
61 printf("%s : Out of memory on line %d\n", __FILE__, __LINE__);
62 printf("Unable to create mxArray.\n");
63 return(EXIT_FAILURE);
64 }
65
66 status = matPutVariable(pmat, "GlobalDouble", pa1);
67 if (status != 0) {
68 printf("%s : Error using matPutVariable on line %d\n", __FILE__, __LINE__);
69 return(EXIT_FAILURE);
70 }
71
72
73
74 /*
75 * Ooops! we need to copy data before writing the array. (Well,
76 * ok, this was really intentional.) This demonstrates that
77 * matPutVariable will overwrite an existing array in a MAT-file.
78 */
79 memcpy((void *)(mxGetPr(pa1)), (void *)data, sizeof(double)*width*height);
80 status = matPutVariable(pmat, "GlobalDouble", pa1);
81 if (status != 0) {
82 printf("%s : Error using matPutVariable on line %d\n", __FILE__, __LINE__);
83 return(EXIT_FAILURE);
84 }
85
86 /* clean up */
87 mxDestroyArray(pa1);
88
89 if (matClose(pmat) != 0) {
90 printf("Error closing file %s\n",file);
91 return(EXIT_FAILURE);
92 }
93
94 /*
95 * Re-open file and verify its contents with matGetVariable
96 */
97 pmat = matOpen(file, "r");
98 if (pmat == NULL) {
99 printf("Error reopening file %s\n", file);
100 return(EXIT_FAILURE);
101 }
102
103 /*
104 * Read in each array we just wrote
105 */
106 pa1 = matGetVariable(pmat, "GlobalDouble");
107 if (pa1 == NULL) {
108 printf("Error reading existing matrix LocalDouble\n");
109 return(EXIT_FAILURE);
110 }
111 if (mxGetNumberOfDimensions(pa1) != 2) {
112 printf("Error saving matrix: result does not have two dimensions\n");
113 return(EXIT_FAILURE);
114 }
115
116
117
118 /* clean up before exit */
119 mxDestroyArray(pa1);
120
121 if (matClose(pmat) != 0) {
122 printf("Error closing file %s\n",file);
123 return(EXIT_FAILURE);
124 }
125 printf("Done\n");
126 return(EXIT_SUCCESS);
127 }
代码的第33~48行是读取一个写有矩阵数据的文件,该文件的前两个int是这个矩阵的行和列。之后就是 行x列 个float型的数据。都读入一个double型的数组中。59和66行的代码就是matlab提供的API。使用这两行代码可以生成一个matlab矩阵。并给这个矩阵起个变量名。最后把之前存在double数组里的数据拷贝到这个matlab矩阵中就可以了。在编译这个代码的时候,要使用mex命令。
打开matlab,输入如下命令
mex('-v', '-f', ['matlabroot' '/bin/matopts.sh'], 'matcreat.cpp')
其中matcreat.cpp就是源文件的名称。matlabroot是matlab安装的路径。生成的可执行文件不一定能执行。我的系统是fedora x64,系统提示我缺少libmat.so。这是因为没有设置好环境变量。在bash中输入如下代码就可以把环境变量设置好,每次启动终端的时候都要如此设置!如果觉得麻烦就写在~/.bashrc中,但是这样在我的fedora15电脑上出现很多莫名其妙的状况。所以不推荐。输入的命令是:
$LD_LIBRARY_PATH=/home/local/MATLAB/R2011b/bin/glnxa64:/home/local/MATLAB/R2011b/sys/os/glnxa64:$LD_LIBRARY_PATH
$export LD_LIBRARY_PATH
这样运行之后可以生成mattest.mat文件,能正常导入到matlab中。
--转自
该贴由koei123转至本版2015-6-2 8:56:15