MEX功能不会初始化左手值

P*_*koV 2 c matlab mex

我必须使用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);  
}
Run Code Online (Sandbox Code Playgroud)

我这样使用它:

n = 5;
T = [];
T = sample(5, T);
Run Code Online (Sandbox Code Playgroud)

此调用返回1×0的空矩阵.因此,它不会分配n-by-n矩阵并且不会填充它.

ray*_*ica 7

你有三个非常关键的错误和一些轻微的打嗝:

  1. 这一行:mwSize n = *(mwSize*)mxGetData(prhs[0]);在你的MEX功能开始时.

    这绝对没有意义.我们可以清楚地看到输入是一个整数. mxGetData实际上获取一个指向实际数据的指针,该实际数据作为MEX函数的输入进入,但是您正在将指针转换为mwSize然后取消引用它.我完全不知道这会给你什么,但它绝对不对.你可以做的是使用mxGetPr指针为你提供符合double精确实数类型的数据的地方获取数据的实际指针.因为这是一个整数,你可以将其强制转换为int:

    int n = (int) *mxGetPr(prhs[0]);
    
    Run Code Online (Sandbox Code Playgroud)
  2. 由于使用(1)进行校正,您现在可以在不显式转换的情况下分配矩阵size_t.我不会称之为错误,但它更像是一种风格修正:

    plhs[0] = mxCreateDoubleMatrix(1, n*n, mxREAL);
    
    Run Code Online (Sandbox Code Playgroud)
  3. 所有人中最重要的错误.

    请注意,sampleMEX代码中的函数接受指向double内存中指针的指针,以便修改在主MEX网关中创建的矩阵(即mexFunction).但是,您首先为要写入输出的矩阵分配内存,但是在函数内部再次分配内存sample.因此,您实际上是在创建另一个指向内存的指针并将数据写入此指针,而不是使用传递给函数的原始指针.具体来说,sample你在里面有这个代码:

    (*T) = (double*)malloc(n*n*sizeof(double));
    
    Run Code Online (Sandbox Code Playgroud)

    因此,退出此函数时,您要修改的内存尚未修改.关键是函数内部的分配不是必需的,因为您已经在函数外部分配了矩阵的内存.这可以从您的代码中删除.

  4. 这在内存访问方面非常重要.请记住,MATLAB是一种基于列主要的语言,这意味着矩阵的列以连续的方式排列,而不是像C这样的语言中的行.因此,您的矩阵访问矩阵的方法是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;
            }
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

    运行此代码后,它现在可以生成所需的结果.但是,您创建了一个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
    
    Run Code Online (Sandbox Code Playgroud)

    如果您希望创建n x n矩阵,请将调用更改为mxCreateDoubleMatrix以便将第一个和第二个参数都设置为n:

    plhs[0] = mxCreateDoubleMatrix(n, n, mxREAL);
    
    Run Code Online (Sandbox Code Playgroud)
  5. 这不是一个错误,但值得挑剔.您的函数只需要1个输入,因此无需提交T第二个参数.无论如何,您的代码不会检查第二个参数.此外,您需要为代码包含正确的标头以进行编译:

    #include <stdlib.h> /* For malloc */
    #include "mex.h" /* For the MEX library */
    
    Run Code Online (Sandbox Code Playgroud)

因此,更正的最终代码是:

#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);  
}
Run Code Online (Sandbox Code Playgroud)

仅仅为了论证,如果改变mxCreateDoubleMatrix以便输出n x n矩阵,则会发生这种情况:

>> mex -O sample.c
Building with 'gcc'.
MEX completed successfully.
>> n = 5;
>> T = sample(n)

T =

     1     0     0     0     0
     0     1     0     0     0
     0     0     1     0     0
     0     0     0     1     0
     0     0     0     0     1
Run Code Online (Sandbox Code Playgroud)