我必须使用MEX函数,该函数应该分配矩阵并填充它(例如,创建一个单位矩阵)。这是一个代码示例:
#include <stdlib.h>
#include "mex.h"
void sample(int n, double** T)
{
(*T) = (double*)malloc(n*n*sizeof(double));
int i, j;
if ((*T) == NULL)
{
return;
}
else
{
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
if (i != j)
(*T)[i*n + j] = 0;
else
(*T)[i*n + j] = 1;
}
}
}
}
void mexFunction( int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[] )
{
mwSize n = *(mwSize*)mxGetData(prhs[0]);
double *T;
plhs[0] = mxCreateDoubleMatrix(1, (size_t)n*(size_t)n, mxREAL);
T = mxGetPr(plhs[0]);
sample(n, &T);
}
我这样用:
n = 5;
T = [];
T = sample(5, T);
此调用返回1×0的空矩阵。因此,它不会分配一个n乘n矩阵,也不会填充它。
答案 0 :(得分:7)
你有三个非常关键的错误和一些轻微的打嗝:
此行:mwSize n = *(mwSize*)mxGetData(prhs[0]);
位于MEX功能的开头。
这绝对没有意义。我们可以清楚地看到输入是一个整数。 mxGetData
实际上获得了指向作为MEX函数输入的实际数据的指针,但是您正在将指针转换为mwSize
然后取消引用它。我完全不知道这会给你什么,但它绝对不对。您可以做的是使用mxGetPr
获取指向数据的实际指针,其中指针将为您提供符合double
精度实数类型的数据。因为这是一个整数,您可以将其强制转换为int
:
int n = (int) *mxGetPr(prhs[0]);
由于使用(1)进行了更正,您现在可以在不使用size_t
显式转换的情况下分配矩阵。我不会称之为错误,但它更像是一种风格修正:
plhs[0] = mxCreateDoubleMatrix(1, n*n, mxREAL);
最重要的错误。
请注意,MEX代码中的sample
函数接受指向内存中double
指针的指针,以便修改您在主MEX网关中创建的矩阵(即{{1 }})。但是,您首先为要写入输出的矩阵分配内存,但在mexFunction
函数内再次分配内存。因此,您实际上是在创建另一个指向内存的指针并将数据写入此指针,而不是使用传递给函数的原始指针。具体来说,在sample
内你有这段代码:
sample
因此,退出此函数时,您要修改的内存未被修改。关键是函数内部的分配不是必需的,因为您已经在函数外部分配了矩阵的内存。这可以从您的代码中删除。
这在内存访问方面非常重要。请记住,MATLAB是一种基于列主要的语言,这意味着矩阵的列以连续的方式排列,而不是像C这样的语言中的行。因此,您的矩阵访问矩阵的方法是大小(*T) = (double*)malloc(n*n*sizeof(double));
,m x n
行和m
列应为n
,其中索引(*T)[j*m + i]
访问行,i
访问列。现在你将它设置为j
。现在,当您的矩阵共享相同的行和列并且您正在创建一个单位矩阵时,任何一种访问方式都是相同的,但是对矩形大小的矩阵感到厌倦。
因此,(*T)[i*n + j]
函数的更正代码为:
sample
运行此代码后,它现在可以生成所需的结果。但是,您创建了void sample(int n, double** T)
{
int i, j;
if (*T == NULL)
{
return;
}
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
if (i != j)
(*T)[j*m + i] = 0;
else
(*T)[j*m + i] = 1;
}
}
}
行向量而不是n*n
矩阵,但我假设您是故意这样做的。为了让它运行,我将你的源代码放在一个名为n x n
的文件中,编译然后运行它:
sample.c
如果您希望创建>> mex -O sample.c
Building with 'gcc'.
MEX completed successfully.
>> n = 5;
>> T = sample(n)
T =
Columns 1 through 19
1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1
Columns 20 through 25
0 0 0 0 0 1
矩阵,请将调用更改为n x n
,以便将第一个和第二个参数都设置为mxCreateDoubleMatrix
:
n
这不是一个错误,但值得挑剔。您的函数只需要1个输入,因此无需提交plhs[0] = mxCreateDoubleMatrix(n, n, mxREAL);
作为第二个参数。无论如何,您的代码不会检查第二个参数。此外,您需要为代码包含正确的标头以进行编译:
T
因此纠正的最终代码是:
#include <stdlib.h> /* For malloc */
#include "mex.h" /* For the MEX library */
仅仅为了争论,如果更改#include <stdlib.h>
#include "mex.h"
void sample(int n, double** T)
{
int i, j;
if (*T == NULL)
{
return;
}
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
if (i != j)
(*T)[j*m + i] = 0;
else
(*T)[j*m + i] = 1;
}
}
}
void mexFunction( int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[] )
{
int n = (int) *mxGetPr(prhs[0]);
double *T;
plhs[0] = mxCreateDoubleMatrix(1, n*n, mxREAL);
/* Change to this line if you wish to have a n x n matrix */
/* plhs[0] = mxCreateDoubleMatrix(n, n, mxREAL); */
T = mxGetPr(plhs[0]);
sample(n, &T);
}
以便输出mxCreateDoubleMatrix
矩阵,会发生这种情况:
n x n