感谢“_者行孙”的文章:https://blog.csdn.net/zhj_matlab/article/details/52972571
文章很好的讲解了混合编程的原因、方法,以及测试用例。
将作者的文章,结合我的工作,以自己的方式总结如下。
一、混合编程的原因
matlab比较擅长矩阵运算,而运算for的速度较慢,如果将matlab与C或C++进行混合编程,则可以提升程序运行速度。
matlab与C/C++的混合编程是通过mexFunction进行的,即在C或C++的源文件中添加一个mexFunction函数,然后通过MX矩阵库和MEX函数库进行编程,以kij.cpp文件为例:
#include "mex.h"
#include "math.h"
// 求高斯核函数
// input:训练集、测试集、参数g;(数据集每列数据为一个特征)
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
// 输入参数
double *p_train, *p_test, p_g; // 每列为一个波形数据,不需要标签数据;
// 输出参数
double *p_k;
// 判断输入参数和输出参数的个数是否正确
mxAssert(nlhs==1 && nrhs==3, "Error: number of variables");
// 输入参数的行列数
int train_rows, train_cols;
int test_rows, test_cols;
train_rows = mxGetM(prhs[0]);// 90 行数:一列是一个波形
train_cols = mxGetN(prhs[0]);// 1099
test_rows = mxGetM(prhs[1]); // 90
test_cols = mxGetN(prhs[1]); // 1099
// 为输出参数分配实数类型内存,存放的是地址
// create output buffer
plhs[0] = mxCreateDoubleMatrix(train_cols, test_cols, mxREAL);
// 获取输入输出参数的地址指针
// get buffer pointers
p_k = (double*)mxGetData(plhs[0]); // 1099*1099
p_train = (double*)mxGetData(prhs[0]);
p_test = (double*)mxGetData(prhs[1]);
p_g = mxGetScalar(prhs[2]); //将第3个输入参数转为Scalar标量,即单数值;
// 代码部分
// matlab数据按列存放和读取。
for (int i = 0; i < test_cols; i++) //对每一个测试样本
{
for (int j = 0; j < train_cols; j++)//每一个训练样本
{
double xTx = 0.0;
for (int m = 0; m < train_rows; m++)
{
xTx = xTx + (p_train[j*train_rows+m] - p_test[i*test_rows+m])*(p_train[j*train_rows+m] - p_test[i*test_rows+m]);
}
p_k[i*train_cols + j] = exp(-p_g * xTx);
}
}
}
首先在代码中引入mex.h头文件,接着编写mexFunction。函数中的四个参数分别表示,int nlhs输出的个数(left hand side),mxArray *plhs[]指向输出变量的mxArray的指针数组,int nrhs输入的个数(right hand side),const mxArray *prhs[]指向输入变量的mxArray的指针数组。函数里面的mx和mex开头的类型和方法皆为mx函数库和mex函数库所提供。
二、VS调试
首先将matlab的当前路径转换到c文件所在的路径,然后在命令窗口或脚本文件中输入mex kij.cpp,这样就可以在matlab中调用kij函数。调用方式如:k11=Kij(data1,data_test1,g);
利用VS2010对源文件调试,步骤如下:
1.切换到Cpp文件所在路径,在命令窗口中输入mex -g Kij.cpp
2.打开VS2010,选择工具->附加到进程,如下图:
3.找到matlab.exe,选中,点击附加。注意此时不要关闭matlab。
4.选择文件,打开有mexFunction的CPP文件,然后设置断点
5.在matlab的命令窗口中输入:k11=Kij(data1,data_test1,g);接着就可以采用VS进行调试。