Matlab API читает файл .mat из c ++, используя контейнер STL

Я должен прочитать некоторые файлы данных .mat из c ++, я прочитал документацию, но мне хотелось бы знать, как обрабатывать данные чистым и элегантным способом, например, использование std: vector (скромный размер файла .mat (10M ~ 1G), но к проблемам памяти следует относиться серьезно)

Моя функция выглядит так:

#include <stdio.h>
#include "mat.h"#include <vector>

int matread(const char *file, const vector<double>& pdata_v) {

MATFile *pmat;

pmat=matOpen("data.mat","r");
if (pmat == NULL) {
printf("Error opening file %s\n", file);
return(1);
}
mxArray *pdata = matGetVariable(pmat, "LocalDouble");

// pdata -> pdata_v

mxDestroy pa1;  // clean up
return 0;
}

Итак, вопрос в том, как мне сделать копию массива mxArray * pdata в вектор pdata_v эффективно и безопасно?

3

Решение

Вот пример использования 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;
}

Сначала мы создаем отдельную программу и создаем некоторые тестовые данные в виде MAT-файла:

>> 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

Теперь мы запускаем программу:

C:\> test_mat.exe
16
5
9
4
2
11
7
14
3
10
6
15
13
8
12
1
9

Другие решения

Вот еще одна идея. Если у вас аллергия на пустые указатели в коде C ++ (кстати, с ними все в порядке), вы можете заключить пустой указатель в буст или интеллектуальный указатель C ++ 11 с помощью средства удаления, которое вызывает правильный mxDestroyArray() когда указатель выходит из области видимости. Таким образом, вам не нужна копия, и при этом ваш пользовательский код не должен знать, как правильно освобождать.

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
}

Идея взята отсюда: http://www.boost.org/doc/libs/1_56_0/libs/smart_ptr/sp_techniques.html#incomplete

3

Вы можете сначала получить указатель данных mxArray *pdata а затем скопировать данные в vector<double> pdata_v:

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

ps1: обратите особое внимание на то, что в MATLAB матрица находится в порядке кол-мажора. Так что если pdata магазины [1 2 3; 4 5 6], pdata_v будет 1 4 2 5 3 6,

PS2: изменить const vector<double>& pdata_v в vector<double>& pdata_v если вы хотите изменить его содержание.

1
По вопросам рекламы [email protected]