2015-04-12 77 views
1

我想用MATLAB-API来读取使用C(不是C++)的.mat文件。从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代码如下:

完整的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; 
} 

回答

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

然后,你需要取消引用它来修改其字段(与->代替.):

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

main,称这样的:

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

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

+0

它的工作和给予我是一个新手,当涉及到C/C++,你的答案是非常有价值的,并感谢。正如你所建议的那样,我已经开始在函数matreadmatread之外声明和释放mexarray。我有一个问题,但。为什么即使我在函数matreadmatread中创建并销毁,我仍然得到正确的结果? –

+0

你能否提出一些关于“**阅读细胞结构**”的建议?我的细胞结构会存储不同大小的矩阵(双)。我完全没有线索。 –

+1

@GarimaSingh如果你在函数内部创建并销毁,它只会在该函数内提供“正确的结果”。在'mxDestroyArray'之后''double *'将会失效。对于更新后的代码,不要忘记将指针初始化为空,所以如果加载失败,销毁不会崩溃'mxArray * arr = NULL;'。关于阅读MEX函数中的MATLAB单元格数组,我建议在用['mxGetCell']给出一个镜头时提出一个新问题(http://www.mathworks.com/help/matlab/apiref/mxgetcell.html ?refresh = true)等。 – chappjc