一、Mex的结构
先看一个简单的程序(该程序保存在matlab主目录下名字是mexDemon.cpp,或者在主目录下新建一个.cpp文件):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
#include "mex.h"
//加入头文件,该头文件在VS2010中无法include,但是不影响其在matlab中的编译,反而在matlab编译还需要include它
#include <vector>
using
namespace
std;
void
mexFunction(
int
nlhs, mxArray *plhs[],
int
nrhs,
const
mxArray *prhs[])
//mexFunction就类似于main函数
{
//nlhs代表的是输出参数的个数
//plhs是一个指针数组,里面的指针指向mxArray类型,每一个指针指向一个输出
//nrhs代表的是输入参数的个数
//prhs是一个指针数组,里面的指针指向mxArray类型,每一个指针指向一个输入
vector<vector<
double
> > array2d;
double
*z;
plhs[0] = mxCreateDoubleMatrix( 5, 6, mxREAL);
//第一个输出是一个5*6的矩阵
z = mxGetPr(plhs[0]);
//获得矩阵的第一个元素的指针
array2d.resize(5);
int
ii = 0;
for
(
int
i = 0; i < 5; i++){
for
(
int
j = 0; j < 6; j++){
z[i*6 + j] = ii;
//指针访问矩阵是列优先的,请自己循环程序和分析输出结果
ii++;
}
}
}
/*
*ans =
0 5 10 15 20 25
1 6 11 16 21 26
2 7 12 17 22 27
3 8 13 18 23 28
4 9 14 19 24 29
*/
|
然后对Matlab编译应用程序mex的编译器进行设置,在命令窗口输入 Mex –setup。 然后跟着步骤走选择合适的编译器即可。
设置完编译器之后在命令窗口输入Mex mexDemon.cpp 进行编译生成.mexw64文件,生成之后便可以直接调用了,例如本例子可以这样调用,就是直接在命令窗口输入 a = mexDemon(); 返回值如上。
二、C和Matlab的数据结构的转换
(1)数值的传递
matlab -> c++
1
|
x = mxGetScalar(prhs[0]);
//该函数获取matlab传递过来的数值;
|
c++ -> matlab
plhs[0] = mxCreateDoubleMatrix(1,1,mxREAL);//创建返回的矩阵,范围plhs[0]为mxArray类型 y = mxGetPr(plhs[0]);//获取返回plhs[0]的数据地址,其后可以修改y的值就可以返回了
一个实例(numDemon.cpp):
1
2
3
4
5
6
7
8
9
10
11
|
#include "mex.h"
void
mexFunction(
int
nlhs, mxArray *plhs[],
int
nrhs,
const
mxArray *prhs[]){
int
x = mxGetScalar(prhs[0]);
//将第一个输入参数转为Scalar标量,也就是单数值
printf
(
"%d\n"
, x);
//打印
double
*y;
plhs[0] = mxCreateDoubleMatrix(1,1,mxREAL);
//让第一个输出参数指向一个1*1的矩阵
y = mxGetPr(plhs[0]);
//获得矩阵的第一个元素的指针
*y = 10;
//将其赋值为10
}
|
如下图在命令窗口编译:
(2)矩阵的传入与传出
关于传出(c++到Matlab, 就是第一个例子),下面可以再给一个例子是如何从matlab传入到c++,看下面这段代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
#include "mex.h"
void
mexFunction(
int
nlhs, mxArray *plhs[],
int
nrhs,
const
mxArray *prhs[]){
double
*dataCursor;
vector<vector<
double
> > parms;
dataCursor = mxGetPr(prhs[0]);
//得到输入矩阵的第一个元素的指针
int
mrows = mxGetM(prhs[0]);
//获得矩阵的行
int
ncols = mxGetN(prhs[0]);
//获得矩阵的列
printf
(
"%d_%d\n"
, mrows, ncols);
//打印行和列
parms.resize(mrows);
//初始化
for
(
int
i = 0; i < mrows; i++){
parms[i].resize(ncols);
}
for
(
int
i = 0; i < mrows; i++){
for
(
int
j = 0; j < ncols; j++){
parms[i][j] = dataCursor[j * mrows + i];
//拷贝矩阵的元素到vector of vector
}
}
}
|
同样在命令窗口编译即可。
(3)字符串的传入与传出
matlab -> c++ (传入)
1
2
|
char
*input_buf;
input_buf = mxArrayToString(prhs[0]);
//使用mxArrayToString将mxArray转换为c、c++字符串
|
c++ -> matlab (传出)
1
2
3
4
5
|
char
*output_buf;
//定义字符串缓存
size_t
buflen = (mxGetM(prhs[0]) * mxGetN(prhs[0])) + 1;
//获取字符串长度,mxGetM获取行数,mxGetN获取列数
output_buf=mxCalloc(buflen,
sizeof
(
char
));
//使用mxCalloc分配输出字符串数组
plhs[0] = mxCreateString(output_buf);
//使用mxCreateString创建mxArray输出
mxfree(output_buf);
|
一个实例(strDemon.cpp)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
#include "mex.h"
void
revord(
char
*input_buf,
size_t
buflen,
char
*output_buf)
{
mwSize i;
if
(buflen == 0)
return
;
for
(i=0;i<buflen-1;i++)
*(output_buf+i) = *(input_buf+buflen-i-2);
}
void
mexFunction(
int
nlhs, mxArray *plhs[],
int
nrhs,
const
mxArray *prhs[])
{
char
*input_buf, *output_buf;
size_t
buflen;
buflen = (mxGetM(prhs[0]) * mxGetN(prhs[0])) + 1;
//因为本程序是翻转字符串,所以输入输出字符串的长度应该一样
output_buf=mxCalloc(buflen,
sizeof
(
char
));
//申请空间
input_buf = mxArrayToString(prhs[0]);
//获得输入字符串
revord(input_buf, buflen, output_buf);
//翻转字符串
plhs[0] = mxCreateString(output_buf);
mxFree(input_buf);
return
;
}
|
同样编译一下即可。
(4)cell的传入
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
#include "mex.h"
void
mexFunction(
int
nlhs, mxArray *plhs[],
int
nrhs,
const
mxArray *prhs[]){
mwSize cellNdim = mxGetNumberOfDimensions(prhs[0]);
//这里介绍两个函数mxGetNumberOfDimensions和mxGetDimensions
const
int
*cellColPtr = mxGetDimensions(prhs[0]);
//mxGetDimensions: 就是返回一个指针ptr,每一个指针所指向的值是每一个维度的元素个数。例如有矩阵3*2的矩阵,那么*(ptr)为3,*(ptr+1)为2.
//mxGetNumberOfDimensions: 返回mxArray的维度。
int
cellNRow = *(label_dims);
int
cellNCol = *(label_dims + 1);
mxArray *ptr;
ptr = mxGetCell(prhs[0], 0);
//获取cell的第0个元素,返回一个mxArray指针,第二个参数代表cell中元素的下标
mxArray *cellOfCell;
cellOfCell = mxGetCell(ptr, 0);
//当然cell里面可以还是cell,那么应该再样写
mxArray *cellOfStr;
char
*chTmp;
cellOfStr = mxGetCell(prhs[0], 0);
//当然cell里面可以是字符串
chTmp = mxArrayToString(cellOfStr);
printf
(
"%s\n"
, chTmp);
}
|