Matlab与C++混合编程–多接口+回调函数
文章目录
一、环境配置
本案例采用MatLab R2014a + Visual Studio 2015。
在matlab命令行中输入mex -setup,查看可以运行的C++编译器或SDK,如果没有安装任何编译器或者SDK则找不到任何编译器。安装编译器或SDK可以参考博客 https://blog.csdn.net/qq_17783559/article/details/82017379。
二、利用C++编写mex库
1.工程属性配置
在VS中创建动态库工程mexTest。
工程属性配置:
目标文件扩展名:.mexw64
包含D:\Program Files\MATLAB\R2014a\extern\include,
依赖D:\Program Files\MATLAB\R2014a\extern\lib\win64\microsoft,
链接库libmex.lib;libeng.lib;libmx.lib;libmat.lib。上述目录是我的matlab安装路径。
编译后生成mexTest.mexw64文件。
2.mexFunction
mexFunction相当于C/C++中main函数,一个mex动态库仅能包含一个mexFunction函数。本次案例中,通过mexFunction调用多个函数,根据函数名称确定要调用的函数,例如add、mutiple、count、callback(回调函数)。利用这种方式能够实现多接口调用。
代码如下(示例):
// nlhs: 函数左侧,输出参数数目 (Left-hand side)
// plhs: 函数左侧,指向输出参数的指针
// nrhs: 函数右侧,输入参数数目
// prhs: 函数右侧,指向输入参数的指针
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
/*if (nlhs != 2 || nrhs != 3) {
mexPrintf("Parameter number err.\n");
return;
}*/
std::string name = mxArrayToString(prhs[0]);
double a = *((double*)mxGetPr(prhs[1]));
double b = *((double*)mxGetPr(prhs[2]));
mexPrintf("name: %s\n",name);
plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);
double* out = (double*)mxGetPr(plhs[0]);
char str[128];
std::strcpy(str, "adadafgfgfghkmnop");
plhs[1] = mxCreateString(str);
if (name == "add")
*out = add(a, b);
else if (name == "mutiple")
*out = mutiple(a, b);
else if(name=="count")
*out = count();
else if (name == "callback")
{
callback(nlhs, plhs, nrhs, prhs);
}
else
*out = 10000000000;
}
3.具体函数实现
add、mutiple、count、callback函数代码如下。callback函数循环十次,调用matlab的myfunc函数。回调函数可参考博客https://blog.csdn.net/tianwenzhe00/article/details/32692255。
回调函数方案:MATLAB调用C文件,再在C文件中调用MATLAB函数(即mex文件中调用matlab函数)。在MEX 文件中添加mexCallMATLAB函数,可实现调用MATLAB函数、用户自定义函数以及MEX函数。mexCallMATLAB通过函数名进行调用。
#include "mex.h"
#include "mexTest.h"
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
int cnt = 0;
int w = 4, h = 3, bits = 10;
double *img;
double add(double a, double b) {
return a + b;
}
double mutiple(double a, double b) {
return a * b;
}
double count() {
return cnt += 1;
}
void callback(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
for (int i = 0; i < 10; i++) {
prhs[1] = mxCreateDoubleMatrix(1, w*h, mxREAL);
double* img = (double*)mxGetPr(prhs[1]);
for (int m = 0; m < h; m++) {
for (int n = 0; n < w; n++) {
img[m*w + n] = m + n + i;
}
}
*((double*)mxGetPr(prhs[2])) = w;
*((double*)mxGetPr(prhs[3])) = h;
*((double*)mxGetPr(prhs[4])) = bits;
mexCallMATLAB(nlhs, (mxArray**)(&plhs[0]), nrhs - 1, (mxArray**)(&prhs[1]), "myfunc");
}
}
4.模块定义文件
在动态库模块定义文件中增加mexFunction函数导出。
代码如下(示例):
LIBRARY "mexTest"
EXPORTS
mexFunction
三、在MatLab中调用mex文件
通过VS编译生成mexTest.mexw64,将该文件复制到MatLab代码运行目录下。
1.test.m
mexTest.mexw64可直接调用,mexTest作为函数名,代码如下所示。
mexTest第一个参数是函数名,指明要调用的函数。后面的参数要根据具体的函数进行变化,例如函数double add(double a, double b)包含两个浮点数参数。
mexTest(‘callback’, 1.0,3.0,3.0,10.0)后面的参数是根据回调函数myfunc.m确定的。参数值可以任意给定,因为在mex库中将重新创建。
[data,str]=mexTest('add', 12.5, 45.6);
[data0,str]=mexTest('mutiple', 12.5, 45.6);
for i=1:11
[data1,str]=mexTest('count', 12.5, 45.6);
end
mexTest('callback', 1.0,3.0,3.0,10.0);
1.编写myfunc.m
function myfunc(img,w,h,bits)
for i=1:w*h
fprintf('%0.0f ',img(i));
end
fprintf('\n');
end
总结
该文章主要记录Matlab调用mex库使用方法。