C ++ Вектор объектов C ++ для mxArray в mex

0

У меня есть следующий вектор c++:

std::vector<myStruct> myVec;

Где myStruct содержит:

struct myStruct {
  Point3D start;
  Point3D end;
  double lenght;
}
struct Point3D {
  double x, y, z;
}

Теперь в моем mex файле я хотел бы преобразовать это в mxArray, сохраняя ту же структуру.

текущий (не функционирующий) код:

// basic 'out' 
mxArray *out;
mwSize dims[2] = { 1, 1 };
const char *pointField[] = {"point"};
const char *fields[] = {"start", "end","lenght"};
const char *3dFields[] =  {"x", "y", "z"};
out = mxCreateStructArray(2,dims,(int)myVec.size(),pointField);
for( int i = 0 ; i < myVec.size() ; ++i)
{
    // create struct to fill
    mxArray *point = mxCreateStructArray(2, dims, 3, fields);

    // create struct for start
    mxArray *start= mxCreateStructArray(2, dims, 3, 3dFields);
    mxSetField( start, 0, "x", mxCreateDoubleScalar(myVec[i].start.x) );
    mxSetField( start, 0, "y", mxCreateDoubleScalar(myVec[i].start.y) );
    mxSetField( start, 0, "z", mxCreateDoubleScalar(myVec[i].start.z) );

    // create struct for end
    mxArray *end= mxCreateStructArray(2, dims, 3, 3dFields);
    mxSetField( end, 0, "x", mxCreateDoubleScalar(myVec[i].end.x) );
    mxSetField( end, 0, "y", mxCreateDoubleScalar(myVec[i].end.y) );
    mxSetField( end, 0, "z", mxCreateDoubleScalar(myVec[i].end.z) );

    // add start + end to 'point'
    mxSetField( point, 0, "start", start);
    mxSetField( point, 0, "end", end); 
    mxSetField( point, 0, "lenght", mxCreateDoubleScalar(myVec[i].lenght) );

    // add completed 'point' struct to out at given index i
    mxSetField(out, i, "point", point );
}
plhs[0] = out;

Как вы можете видеть, важно, чтобы у меня было 1 выходное значение, которое может содержать несколько "точек" -structs, из которых каждая точка имеет начало (xyz) -struct, end (xyz) -struct и значение длины.

Пока этот код выводит только одну структуру в правильном формате, но затем для второй итерации он создает только пустые значения "end" непосредственно на уровне, где "точка".

Что мне нужно изменить, чтобы эта работа работала правильно?

Заранее спасибо!

  • 1
    Ваш код C ++ не делает то, что вы описываете, ни то, что пытается сделать ваш код MEX. start и end являются векторами точек, а не отдельных точек, и ваш MEX-файл пытается получить к ним доступ с помощью функций доступа. Пожалуйста, оставьте свой реальный код.
  • 0
    Также рассмотрите пример того, как вы хотите получить доступ к полученной структуре MATLAB. Я думаю, что вы смешали код, который дал бы вам myVec.point(17).start.x против myVec(17).point.start.x , и я думаю, что вы, вероятно, хотите вместо myVec(17).start.x . Но я просто догадываюсь.
Показать ещё 1 комментарий
Теги:
mex

2 ответа

4
Лучший ответ

Вот моя реализация:

vec_struct.cpp

#include "mex.h"
#include <vector>

// C++ struct
struct Point3D {
    double x, y, z;
};
struct myStruct {
    Point3D start;
    Point3D end;
    double length;
};

const char *fieldsPoint[] = {"x", "y", "z"};
const char *fieldsStruct[] = {"start", "end", "length"};

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    if (nrhs != 0 || nlhs > 1) {
        mexErrMsgIdAndTxt("MATLAB:MEX", "Wrong number of arguments.");
    }

    // create C++ vector of structs
    std::vector<myStruct> v;
    for (int i=0; i<10; i++) {
        myStruct s = {
            {1.0+i, 2.0+i, 3.0+i},
            {4.0+i, 5.0+i, 6.0+i},
            i
        };
        v.push_back(s);
    }

    // convert it to MATLAB struct array and return it as output
    mxArray *p;
    plhs[0] = mxCreateStructMatrix(1, v.size(), 3, fieldsStruct);
    for (int i=0; i<v.size(); i++) {
        // start point
        p = mxCreateStructMatrix(1, 1, 3, fieldsPoint);
        mxSetField(p, 0, "x", mxCreateDoubleScalar(v[i].start.x));
        mxSetField(p, 0, "y", mxCreateDoubleScalar(v[i].start.y));
        mxSetField(p, 0, "z", mxCreateDoubleScalar(v[i].start.z));
        mxSetField(plhs[0], i, "start", p);

        // end point
        p = mxCreateStructMatrix(1, 1, 3, fieldsPoint);
        mxSetField(p, 0, "x", mxCreateDoubleScalar(v[i].end.x));
        mxSetField(p, 0, "y", mxCreateDoubleScalar(v[i].end.y));
        mxSetField(p, 0, "z", mxCreateDoubleScalar(v[i].end.z));
        mxSetField(plhs[0], i, "end", p);

        // length
        mxSetField(plhs[0], i, "length", mxCreateDoubleScalar(v[i].length));
    }
}

Мы компилируем и вызываем MEX-функцию из MATLAB:

>> mex -largeArrayDims vec_struct.cpp
>> s = vec_struct()
s = 
1x10 struct array with fields:
    start
    end
    length

Как вы можете видеть, это создает массив структуры длиной 10. Например, 5-ю структуру получает доступ как:

>> s(5)
ans = 
     start: [1x1 struct]
       end: [1x1 struct]
    length: 4
>> s(5).start
ans = 
    x: 5
    y: 6
    z: 7
>> s(5).start.x
ans =
     5

Вышеуказанный MEX файл эквивалентен следующему коду MATLAB:

ss = struct();
for i=1:10
    ss(i).start  = struct('x',1+i-1, 'y',2+i-1, 'z',3+i-1);
    ss(i).end    = struct('x',4+i-1, 'y',5+i-1, 'z',6+i-1);
    ss(i).length = i-1;
end
  • 0
    Спасибо, работал как шарм! :)
0

Я вижу два вопроса (не обязательно полный):

  1. out создается как скалярная структура в вашем коде, вместо этого он должен, вероятно, быть

    out = mxCreateStructMatrix(1, (int)myVec.size(), 3, pointField);

  2. Вы указываете const char *fields[] = {"start", "end","depth"}; но затем вы пытаетесь установить поле lenght.

Первой проблемой может быть причина вашего наблюдения - в mex вам придется предварительно распределить матрицу структуры соответствующим образом.

  • 0
    Исправлена ошибка поля "глубина", действительно должна была быть "длина". Спасибо! Я попробую CreateStructMatrix, чтобы увидеть, решит ли он мою проблему :)
  • 0
    CreateStructMatrix не является важным отличием. Важным отличием являются размеры массива, который здесь равен 1xN, а не 1x1 с N полями.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню