Matlab API reading .mat file from c++, using STL container

前端 未结 3 1850
予麋鹿
予麋鹿 2020-12-05 08:58

I have to read some .mat data files from c++, I read through the documentation, but I would like to know how to handle the data in a clean and elegant way, e.g. using std:ve

相关标签:
3条回答
  • 2020-12-05 09:21

    Here's another idea. If you're allergic to bare pointers in C++ code (nothing wrong with them, by the way), you could wrap the bare pointer in a boost or C++11 smart pointer with a deleter that calls the correct mxDestroyArray() when the pointer goes out of scope. That way you don't need a copy, nor does your user code need to know how to correctly deallocate.

    typedef shared_ptr<mxArray> mxSmartPtr;
    
    mxSmartPtr readMATarray(MATFile *pmat, const char *varname)
    {
        mxSmartPtr pdata(matGetVariable(pmat, varname),
                         mxDestroyArray);  // set deleter
        return pdata;
    }
    
    int some_function() {
        mxSmartPtr pdata = readMATarray(pmat, "LocalDouble");
        ...
        // pdata goes out of scope, and mxDestroy automatically called
    }
    

    Idea taken from here: http://www.boost.org/doc/libs/1_56_0/libs/smart_ptr/sp_techniques.html#incomplete

    0 讨论(0)
  • 2020-12-05 09:24

    You can first get the data pointer of the mxArray *pdata and then copy data to vector<double> pdata_v:

    double *ptr = (double *) mxGetData(pdata);
    pdata_v.resize(numOfData);
    memcpy(&pdata_v[0], ptr, numOfData*sizeof(double));
    

    ps1: Pay extra attention to that, in MATLAB, matrice are in col-major order. So if pdata stores [1 2 3; 4 5 6], pdata_v will be 1 4 2 5 3 6.

    ps2: Change const vector<double>& pdata_v to vector<double>& pdata_v if you want to change its content.

    0 讨论(0)
  • 2020-12-05 09:32

    Here is an example of using the MAT-API:

    test_mat.cpp

    #include "mat.h"
    #include <iostream>
    #include <vector>
    
    void matread(const char *file, std::vector<double>& v)
    {
        // open MAT-file
        MATFile *pmat = matOpen(file, "r");
        if (pmat == NULL) return;
    
        // extract the specified variable
        mxArray *arr = matGetVariable(pmat, "LocalDouble");
        if (arr != NULL && mxIsDouble(arr) && !mxIsEmpty(arr)) {
            // copy data
            mwSize num = mxGetNumberOfElements(arr);
            double *pr = mxGetPr(arr);
            if (pr != NULL) {
                v.reserve(num); //is faster than resize :-)
                v.assign(pr, pr+num);
            }
        }
    
        // cleanup
        mxDestroyArray(arr);
        matClose(pmat);
    }
    
    int main()
    {
        std::vector<double> v;
        matread("data.mat", v);
        for (size_t i=0; i<v.size(); ++i)
            std::cout << v[i] << std::endl;
        return 0;
    }
    

    First we build the standalone program, and create some test data as a MAT-file:

    >> mex -client engine -largeArrayDims test_mat.cpp
    
    >> LocalDouble = magic(4)
    LocalDouble =
        16     2     3    13
         5    11    10     8
         9     7     6    12
         4    14    15     1
    
    >> save data.mat LocalDouble
    

    Now we run the program:

    C:\> test_mat.exe
    16 
    5 
    9 
    4 
    2 
    11 
    7 
    14 
    3 
    10 
    6 
    15 
    13 
    8 
    12 
    1 
    
    0 讨论(0)
提交回复
热议问题