【问题标题】:Reading .mat file from C: Can read variable ; but cannot return PROPERLY从 C 读取 .mat 文件:可以读取变量;但不能正确返回
【发布时间】:2015-04-13 01:43:48
【问题描述】:

我正在尝试使用 MATLAB-API 使用 C(不是 C++)读取 .mat 文件。

这是 MATLAB 代码,可以创建我想要的某种 .mat 文件:

A = [[1 2 3]; [5 7 1]; [3 5 9]];
B = [[2 4];[5 7]];
Creator = 'DKumar';

nFilters = 2;

Filters{1} = [[-1.0 -1.0 -1.0]; [-1.0 8 -1.0]; [-1.0 -1.0 -1.0]];
Filters{2} = 2.0*[[-1.0 -1.0 -1.0]; [-1.0 8 -1.0]; [-1.0 -1.0 -1.0]];

cd('/home/dkumar/CPP_ExampleCodes_DKU/Read_mat_File');
save('Test_FILE.mat', 'A', 'B', 'Creator', 'nFilters', 'Filters');

请注意,我还需要阅读单元结构或类似的内容。

(1) 在 C 代码中,我似乎可以很好地读取存储在 .mat 中的矩阵; 但是,不能正常返回(见最后的输出)。

(2) 我仍然不知道单元结构,在这个例子中它会存储大小可能不同的双矩阵。

完整的 C 代码如下。首先是函数matread,貌似可以正常读取数据。

#include <stdio.h>
#include <stdlib.h>
#include "/usr/local/MATLAB/R2011b/extern/include/mat.h"


struct stDoubleMat{
   double* pValueInField;
   int nRows, nCols;
};

void matread(const char *file, const char *FieldName2Read, struct stDoubleMat oDoubleMat_LOC)
{
    printf("Reading file %s...\n\n", file);

    //Open file to get directory
    MATFile* pmat = matOpen(file, "r");

    if (pmat == NULL) {
      printf("Error opening file %s\n", file);
      return;
    }

    // extract the specified variable
    mxArray *arr = matGetVariable(pmat, FieldName2Read);

    double *pr;
    if (arr != NULL && !mxIsEmpty(arr)) {
        // copy data
        mwSize num = mxGetNumberOfElements(arr);

        pr = mxGetPr(arr);

        if (pr != NULL) {
        oDoubleMat_LOC.pValueInField = pr;
            oDoubleMat_LOC.nRows  = mxGetM(arr);
            oDoubleMat_LOC.nCols  = mxGetN(arr);
        }
    printf("From inside the function \n") ;
        printf( "oDoubleMat_LOC.nRows %i ; oDoubleMat_LOC.nCols %i \n", oDoubleMat_LOC.nRows , oDoubleMat_LOC.nCols);

    }else{
        printf("nothing to read \n") ;
    }

    // cleanup
    mxDestroyArray(arr);
    matClose(pmat);

    return;
}

在同一个文件中,main函数,似乎无法返回读取的数据:

int main(int argc, char **argv)
{
    const char *FileName = "/home/dkumar/CPP_ExampleCodes_DKU/Read_mat_File/Test_FILE.mat";
    const char *FieldName2Read = "A";

    struct stDoubleMat oDoubleMat; 
    matread(FileName, FieldName2Read, oDoubleMat);
    double* v = oDoubleMat.pValueInField;


    printf("From main \n");
    printf( "oDoubleMat.nRows %i ; oDoubleMat.nCols %i \n", oDoubleMat.nRows , oDoubleMat.nCols);
/*
    for (int i = 0; i < oDoubleMat.nElements; i++)
    {
        std::cout <<" copied value : " << *v << "\n";
        v = v +1;
    }*/

    return 0;
}

这是输出

$ gcc -o Test Read_MatFile_DKU_2.c -I/usr/local/MATLAB/R2011b/extern/include -L/usr/local/MATLAB/R2011b/bin/glnxa64 -lmat -lmx

$ ./Test 
Reading file /home/dkumar/CPP_ExampleCodes_DKU/Read_mat_File/Test_FILE.mat...

From inside the function 
oDoubleMat_LOC.nRows 3 ; oDoubleMat_LOC.nCols 3 
From main 
oDoubleMat.nRows 0 ; oDoubleMat.nCols 0 

更新:

这是读取矩阵字段的更新代码。我还有 no clue about how to read "cell-structure"

#include <stdio.h>
#include <stdlib.h>
#include "/usr/local/MATLAB/R2011b/extern/include/mat.h"

mxArray *arr;

struct stDoubleMat{
   double* pValueInField;
   int nRows, nCols;
};

void matread(const char *file, const char *FieldName2Read, struct stDoubleMat* poDoubleMat_LOC)
{
    printf("Reading file %s...\n\n", file);

    //Open file to get directory
    MATFile* pmat = matOpen(file, "r");

    if (pmat == NULL) {
      printf("Error opening file %s\n", file);
      return;
    }

    // extract the specified variable
    arr = matGetVariable(pmat, FieldName2Read);

    double *pr;
    if (arr != NULL && !mxIsEmpty(arr)) {
        // copy data
        mwSize num = mxGetNumberOfElements(arr);

        pr = mxGetPr(arr);

        if (pr != NULL) {
        poDoubleMat_LOC->pValueInField = pr;
            poDoubleMat_LOC->nRows  = mxGetM(arr);
            poDoubleMat_LOC->nCols  = mxGetN(arr);
        }
    printf("From inside the function \n") ;
        printf( "oDoubleMat_LOC.nRows %i ; oDoubleMat_LOC.nCols %i \n", poDoubleMat_LOC->nRows , poDoubleMat_LOC->nCols);

    }else{
        printf("nothing to read \n") ;
    }

    // close the file
    matClose(pmat);

    return;
}

int main(int argc, char **argv)
{
    const char *FileName = "/home/dkumar/CPP_ExampleCodes_DKU/Read_mat_File/Test_FILE.mat";
    const char *FieldName2Read = "A";

    struct stDoubleMat oDoubleMat; 
    matread(FileName, FieldName2Read, &oDoubleMat);
    double* v = oDoubleMat.pValueInField;


    printf("From main \n");
    printf( "oDoubleMat.nRows %i ; oDoubleMat.nCols %i \n", oDoubleMat.nRows , oDoubleMat.nCols);

    int i;
    for (i = 0; i < oDoubleMat.nCols*oDoubleMat.nRows; i++)
    {
        printf(" copied value : %f \n", *v);
        v = v +1;
    }

    // cleanup the mex-array
    mxDestroyArray(arr);

    return 0;
}

【问题讨论】:

    标签: c matlab mex


    【解决方案1】:

    您将“输出”参数 (oDoubleMat_LOC) 按值传递给 matread,因此您永远无法真正获得输出,因为它是在输入上复制的(即仅在本地修改):

    void matread(const char *file, const char *FieldName2Read, 
        struct stDoubleMat oDoubleMat_LOC) /* oDoubleMat_LOC copied */
    

    由于您使用的是 C 语言,其中引用不可用,因此请传递一个指针。重新定义matread

    void matread(const char *file, const char *FieldName2Read, 
        struct stDoubleMat *oDoubleMat_LOC) /* use a pointer */
    

    然后在matread 中,您需要取消引用它以修改其字段(使用-&gt; 而不是.):

    oDoubleMat_LOC->pValueInField = pr;
    oDoubleMat_LOC->nRows  = mxGetM(arr);
    oDoubleMat_LOC->nCols  = mxGetN(arr);
    

    main,这样调用:

    struct stDoubleMat oDoubleMat; 
    matread(FileName, FieldName2Read, &oDoubleMat);
    

    但是,请注意你有更大的问题,因为支持double *pValueInFieldmxArraymatread 内部分配和销毁。虽然您可以返回指向数据数组的指针,但它将是一个悬空指针,指向已释放的数据。您需要在matread 之外分配一个mxArray 并将其传入,或者分配一个double * 并将数据复制到matread 内部。否则,只要调用mxDestroyArray,指针就没有用了。

    【讨论】:

    • 它奏效了,考虑到我是 C/C++ 的新手,您的回答非常有价值,感谢您的回答。正如您所建议的,我已经开始在函数 matreadmatread 之外声明和销毁 mexarray。我有一个问题。为什么即使我在matreadmatread函数内部创建和销毁,我仍然得到正确的结果?
    • 您能否推荐一些关于“阅读细胞结构”的内容?我的单元结构将存储不同大小的矩阵(双)。我完全不知道。
    • @GarimaSingh 如果您在函数内部创建和销毁,它只会在该函数内部给出“正确的结果”。 double *mxDestroyArray 之后将失效。对于您更新的代码,请不要忘记将指针初始化为 null,因此如果加载失败 mxArray *arr = NULL;,destroy 不会崩溃。关于在 MEX 函数中读取 MATLAB 元胞数组,我建议您在尝试使用 mxGetCell 等后提出一个新问题。
    猜你喜欢
    • 2016-07-23
    • 1970-01-01
    • 2014-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多