目录
创建 C 源 MEX 文件
此示例说明如何编写 MEX 文件,以在 MATLAB® 中使用在 C 矩阵 API 中定义的 MATLAB 数组调用 C 函数 arrayProduct。可以在此处查看完整的源文件。
要使用此示例,需要:
-
能够编写 C 或 C++ 源代码。您使用 MATLAB 编辑器创建这些文件。
-
MATLAB 支持的编译器。
-
C 矩阵 API 和 C MEX API中的函数。
-
mex编译脚本。
C 函数 arrayProduct
以下代码定义 arrayProduct 函数,它将 1×n 矩阵 y 与标量值 x 相乘,并以数组 z 形式返回结果。可以在 C++ 应用程序中使用这些相同的 C 语句。
void arrayProduct(double x, double *y, double *z, int n)
{
int i;
for (i=0; i<n; i++) {
z[i] = x * y[i];
}
}
创建源文件
打开 MATLAB 编辑器,创建一个文件,并在 MEX 文件中记录以下信息。
/*
* arrayProduct.c - example in MATLAB External Interfaces
*
* Multiplies an input scalar (multiplier)
* times a 1xN matrix (inMatrix)
* and outputs a 1xN matrix (outMatrix)
*
* The calling syntax is:
*
* outMatrix = arrayProduct(multiplier, inMatrix)
*
* This is a MEX file for MATLAB.
*/
添加包含 MATLAB API 函数声明的 C/C++ 头文件 mex.h。
#include "mex.h"
将文件保存在您的 MATLAB 路径(例如 c:\work)中,并将其命名为 arrayProduct.c。您的 MEX 文件名称为 arrayProduct。
创建入口例程
每个 C 程序都有一个 main() 函数。MATLAB 使用入口例程 mexFunction 作为函数的入口函数。添加以下 mexFunction 代码。
/* The gateway function */
void mexFunction(int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
{
/* variable declarations here */
/* code here */
}
下表描述了 mexFunction 的输入参数。
参数 | 说明 |
---|---|
nlhs | 输出(左侧)参数的数量,或 plhs 数组的大小。 |
plhs | 输出参数的数组。 |
nrhs | 输入(右侧)参数的数量,或 prhs 数组的大小。 |
prhs | 输入参数的数组。 |
验证 MEX 文件的输入和输出参数
使用 nrhs 和 nlhs 参数验证 MEX 文件输入和输出参数的数量。要检查两个输入参数 multiplier 和 inMatrix,请使用以下代码。
if(nrhs != 2) {
mexErrMsgIdAndTxt("MyToolbox:arrayProduct:nrhs",
"Two inputs required.");
}
使用以下代码检查一个输出参数,即乘积 outMatrix。
if(nlhs != 1) {
mexErrMsgIdAndTxt("MyToolbox:arrayProduct:nlhs",
"One output required.");
}
使用 plhs 和 prhs 参数验证参数类型。以下代码将验证 multiplier(由 prhs[0] 表示)为标量。
/* make sure the first input argument is scalar */
if( !mxIsDouble(prhs[0]) ||
mxIsComplex(prhs[0]) ||
mxGetNumberOfElements(prhs[0]) != 1 ) {
mexErrMsgIdAndTxt("MyToolbox:arrayProduct:notScalar",
"Input multiplier must be a scalar.");
}
以下代码将验证 inMatrix(由 prhs[1] 表示)为 double 类型。
if( !mxIsDouble(prhs[1]) ||
mxIsComplex(prhs[1])) {
mexErrMsgIdAndTxt("MyToolbox:arrayProduct:notDouble",
"Input matrix must be type double.");
}
验证 inMatrix 为行向量。
/* check that number of rows in second input argument is 1 */
if(mxGetM(prhs[1]) != 1) {
mexErrMsgIdAndTxt("MyToolbox:arrayProduct:notRowVector",
"Input must be a row vector.");
}
创建计算例程
添加 arrayProduct 代码。以下函数计算例程,即用于执行在 MATLAB 中使用的功能的源代码。
void arrayProduct(double x, double *y, double *z, int n)
{
int i;
for (i=0; i<n; i++) {
z[i] = x * y[i];
}
}
计算例程是可选的。您也可以将代码置于 mexFunction 函数块中。
编写代码以实现跨平台的灵活性
MATLAB 提供了基于平台表示整数大小值的预处理器宏 mwsize。计算例程将数组的大小声明为 int。将变量 n 和 i 的 int 声明替换为 mwsize。
void arrayProduct(double x, double *y, double *z, mwSize n)
{
mwSize i;
for (i=0; i<n; i++) {
z[i] = x * y[i];
}
}
声明计算例程的变量
将以下变量声明置于 mexFunction 中。
-
声明输入参数的变量。
double multiplier; /* input scalar */ double *inMatrix; /* 1xN input matrix */
-
为输入矩阵的大小声明 ncols。
mwSize ncols; /* size of matrix */
-
声明输出参数 outMatrix。
double *outMatrix; /* output matrix */
稍后,将 mexFunction 参数赋给这些变量。
读取输入数据
要读取标量输入,请使用 mxGetScalar 函数。
/* get the value of the scalar input */
multiplier = mxGetScalar(prhs[0]);
使用 mxGetDoubles 函数指向输入矩阵数据。
/* create a pointer to the real data in the input matrix */
inMatrix = mxGetDoubles(prhs[1]);
使用 mxGetN 函数获取矩阵大小。
/* get dimensions of the input matrix */
ncols = mxGetN(prhs[1]);
准备输出数据
要创建输出参数 plhs[0],请使用 mxCreateDoubleMatrix 函数。
/* create the output matrix */
plhs[0] = mxCreateDoubleMatrix(1,ncols,mxREAL);
使用 mxGetDoubles 函数将 outMatrix 参数赋给 plhs[0]
/* get a pointer to the real data in the output matrix */
outMatrix = mxGetDoubles(plhs[0]);
执行计算
将参数传递给 arrayProduct。
/* call the computational routine */
arrayProduct(multiplier,inMatrix,outMatrix,ncols);
查看完整的源文件
将源文件与位于 matlabroot/extern/examples/mex 的arrayProduct.c进行比较。在编辑器中打开文件 arrayProduct.c。
编译 MEX 函数
在 MATLAB 命令提示符下,使用mex命令编译该函数。
mex arrayProduct.c -R2018a
测试 MEX 函数
s = 5;
A = [1.5, 2, 9];
B = arrayProduct(s,A)
B =
7.5000 10.0000 45.0000
验证 MEX 文件输入参数
最好在调用 MEX 函数之前验证 MATLAB 变量的类型。要测试输入变量 inputArg 并在必要时将其转换为 double,请使用以下代码。
s = 5;
A = [1.5, 2, 9];
inputArg = int16(A);
if ~strcmp(class(inputArg),'double')
inputArg = double(inputArg);
end
B = arrayProduct(s,inputArg)