2015-04-12 72 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