Lire un fichier .mat en utilisant C: comment lire correctement la structure de cellule

J’essaie essentiellement de traduire le code Matlab en code C. Ceci est le prolongement de ma question précédente.

Dans Matlab, j’ai utilisé cell-structures masortingces (double) of variable sizes . Voici un exemple jouet de ce que mon fichier * .mat est supposed to store :

Code Matlab:

 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 8]; [-1.0 -1.0]]; cd('/home/dkumar/CPP_ExampleCodes_DKU/Read_mat_File'); save('Test_FILE.mat', 'A', 'B', 'Creator', 'nFilters', 'Filters'); 

C-code: La fonction "matread_Masortingx" reads masortingces stored in *.mat properly . C’est la fonction "matread_Cell" , qui est supposée lire la structure de cellule, not working .

 #include  #include  #include "/usr/local/MATLAB/R2011b/extern/include/mat.h" mxArray *arr; mxArray *C_CELL; /* declare a 2 x 1 array of pointers to access the cell array in C */ mxArray *cellArray[2]; struct stDoubleMat{ double* pValueInField; int nRows, nCols; }; void matread_Masortingx(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("matread_Masortingx \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; } void matread_Cell(const char *file, const char *FieldName2Read, int CellIndex) { 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 C_CELL = matGetVariable(pmat, FieldName2Read); cellArray[CellIndex] = mxGetCell(C_CELL, CellIndex); double* p2 = (double*)cellArray[CellIndex]; int nRows = mxGetM(cellArray[CellIndex]); int nCols = mxGetN(cellArray[CellIndex]); printf(" From inside matread_Cell : nRows %i and nCols %i \n", nRows, nCols); int i2; for (i2 = 0; i2 < nRows*nCols; i2++) { printf(" copied value : %f \n", *p2); p2 = p2 +1; } // close the file matClose(pmat); } 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_Matrix(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; } // Reading the structure const char *FieldName2Read2 = "Filters"; matread_Cell(FileName, FieldName2Read2, 0); matread_Cell(FileName, FieldName2Read2, 1); // cleanup the mex-array mxDestroyArray(arr); mxDestroyArray(C_CELL); /* How to delete mxArray of pointer : should this be a array of pointers */ //mxDestroyArray(cellArray[0]); //mxDestroyArray(cellArray[1]); return 0; } 

Sortie:

 $ gcc -g -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... matread_Masortingx oDoubleMat_LOC.nRows 3 ; oDoubleMat_LOC.nCols 3 From main oDoubleMat.nRows 3 ; oDoubleMat.nCols 3 copied value : 1.000000 copied value : 5.000000 copied value : 3.000000 copied value : 2.000000 copied value : 7.000000 copied value : 5.000000 copied value : 3.000000 copied value : 1.000000 copied value : 9.000000 Reading file /home/dkumar/CPP_ExampleCodes_DKU/Read_mat_File/Test_FILE.mat... From inside matread_Cell : nRows 3 and nCols 3 copied value : 0.000000 copied value : 0.000000 copied value : 0.000000 copied value : 0.000000 copied value : 0.000000 copied value : 0.000000 copied value : 0.000000 copied value : 0.000000 copied value : 0.000000 Reading file /home/dkumar/CPP_ExampleCodes_DKU/Read_mat_File/Test_FILE.mat... From inside matread_Cell : nRows 3 and nCols 2 copied value : 0.000000 copied value : 0.000000 copied value : 0.000000 copied value : 0.000000 copied value : 0.000000 copied value : 0.000000 

De plus, je ne pouvais pas lire ce champ correctement: Creator = ‘DKumar’;

METTRE À JOUR:

Basé sur la suggestion de @Sherwin

Mon code C:

 #include  #include  #include "/usr/local/MATLAB/R2011b/extern/include/mat.h" mxArray *arr; mxArray *C_CELL; /* declare a 2 x 1 array of pointers to access the cell array in C */ mxArray *cellArray[2]; struct stDoubleMat{ double* pValueInField; int nRows, nCols; }; void matread_Masortingx(MATFile* pmat , const char *FieldName2Read, struct stDoubleMat* poDoubleMat_LOC) { // 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("matread_Masortingx \n") ; printf( "oDoubleMat_LOC.nRows %i ; oDoubleMat_LOC.nCols %i \n", poDoubleMat_LOC->nRows , poDoubleMat_LOC->nCols); }else{ printf("nothing to read \n") ; } return; } void matread_Ssortingng(MATFile* pmat , const char *FieldName2Read) { // 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) { char *p2 = (char*) pr; // Printing and checking int i2; for (i2 = 0; i2 < num; i2++) { printf(" copied value : %s \n", p2); p2 = p2 +1; } } }else{ printf("nothing to read \n") ; } return; } void matread_Cell(MATFile* pmat , const char *FieldName2Read, int CellIndex) { // extract the specified variable C_CELL = matGetVariable(pmat, FieldName2Read); cellArray[CellIndex] = mxGetCell(C_CELL, CellIndex); double *p2 = (double*) mxGetPr(cellArray[CellIndex]); int nRows = mxGetM(cellArray[CellIndex]); int nCols = mxGetN(cellArray[CellIndex]); printf(" From inside matread_Cell : nRows %i and nCols %i \n", nRows, nCols); int i2; for (i2 = 0; i2 < nRows*nCols; i2++) { printf(" copied value : %f \n", *p2); p2 = p2 +1; } } int main(int argc, char **argv) { const char *FileName = "/home/dkumar/CPP_ExampleCodes_DKU/Read_mat_File/Test_FILE.mat"; const char *FieldName2Read = "A"; //Open file to get directory printf("Reading file %s...\n\n", FileName); MATFile* pmat = matOpen(FileName, "r"); if (pmat == NULL) { printf("Error opening file %s\n", FileName); return; } struct stDoubleMat oDoubleMat; matread_Matrix(pmat, FieldName2Read, &oDoubleMat); double* v = oDoubleMat.pValueInField; int i; for (i = 0; i < oDoubleMat.nCols*oDoubleMat.nRows; i++) { printf(" copied value : %f \n", *v); v = v +1; } // Reading the structure const char *FieldName2Read2 = "Filters"; matread_Cell(pmat, FieldName2Read2, 0); matread_Cell(pmat, FieldName2Read2, 1); // Reading the string const char *FieldName2Read3 = "Creator"; matread_String(pmat, FieldName2Read3); // cleanup the mex-array mxDestroyArray(arr); mxDestroyArray(C_CELL); /* How to delete mxArray of pointer : should this be a array of pointers */ //mxDestroyArray(cellArray[0]); //mxDestroyArray(cellArray[1]); // close the file matClose(pmat); return 0; } 

Sortie:

 oDoubleMat.nRows 3 ; oDoubleMat.nCols 3 copied value : 1.000000 copied value : 5.000000 copied value : 3.000000 copied value : 2.000000 copied value : 7.000000 copied value : 5.000000 copied value : 3.000000 copied value : 1.000000 copied value : 9.000000 From inside matread_Cell : nRows 3 and nCols 3 copied value : -1.000000 copied value : -1.000000 copied value : -1.000000 copied value : -1.000000 copied value : 8.000000 copied value : -1.000000 copied value : -1.000000 copied value : -1.000000 copied value : -1.000000 From inside matread_Cell : nRows 3 and nCols 2 copied value : -2.000000 copied value : -2.000000 copied value : -2.000000 copied value : -2.000000 copied value : 16.000000 copied value : -2.000000 copied value : D copied value : copied value : K copied value : copied value : u copied value : copied value : 

Problème: 1) La valeur de chaîne stockée dans le créateur ne s’affiche pas correctement.

2) Comment supprimer cellArray [2])?

Avec un léger changement, votre code fonctionne:

Dans la fonction ” void matread_Cell “, remplacez la ligne double* p2 = (double*)cellArray[CellIndex]; avec:

 p2 = (double*) mxGetPr(cellArray[CellIndex]); 

Je l’ai vérifié. Ça fait le travail.

De plus, pour lire le champ créateur, un code similaire à mtread_masortingx devrait fonctionner, mais le type est char* au lieu de double* (je n’ai pas vérifié celui-ci. Faites-moi savoir si cela ne fonctionne pas).

update: vous pouvez utiliser le code suivant pour lire des chaînes. (Référence: ici )

 void matread_ssortingng(const char *file, const char *FieldName2Read, char *pr, mwSize *len) { 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); if (arr != NULL && !mxIsEmpty(arr)) { // copy data mwSize num = mxGetNumberOfElements(arr); //int mxGetSsortingng(const mxArray *pm, char *str, mwSize strlen); int res= mxGetSsortingng(arr, pr, num+1); //strlen should be len+1. cf reference. if(res==0) printf("success!\n"); else printf("failed.\n"); if ( pr == NULL){ printf("null pointer.\n"); } printf("matread_ssortingng \n") ; printf( "len: %i \n", (int)num); *len=num; }else{ printf("nothing to read \n") ; } // close the file matClose(pmat); return; } 

En main vous pouvez l’utiliser comme:

  const char *FieldName2Read3 = "Creator"; char pr[20]; mwSize len; matread_ssortingng(FileName, FieldName2Read3, pr, &len); //int i; printf(" copied value: %s \n",pr); for (i = 0; (mwSize) i < len; i++) { printf(" copied value : %c \n", pr[i]); } 

En ce qui concerne le désallocation de cellArray, j'obtiens l'erreur suivante: "le pointeur libéré n'a pas été atsortingbué", je ne pense donc pas que vous deviez libérer cela. Une autre commande utile pour libérer de la mémoire dynamic est la suivante: void mxFree(void *ptr);

En ce qui concerne la fonction mexPrintf , je suis en mesure de l’utiliser. Je viens d'obtenir une implicit declaration of function 'mexPrintf' is invalid in C99 [-Wimplicit-function-declaration] avertissement implicit declaration of function 'mexPrintf' is invalid in C99 [-Wimplicit-function-declaration] , car je comstack via gcc plutôt que mex. Si vous utilisez gcc, vous devrez probablement inclure les bibliothèques appropriées pour reconnaître cette fonction. Vous trouverez peut-être cela utile, car cela a fonctionné pour moi.