首页 文章

C C的向量对象在mex中的mxArray

提问于
浏览
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个输出值,它可以包含多个“点” - 结构,每个点都有一个start(xyz)-struct,end(xyz)-struct和lenght值 .

到目前为止,这段代码只以正确的格式输出1个单一结构,但是对于第二次迭代,它只在“点”所在的级别直接创建一个空的“结束”值 .

我需要更改才能正常工作?

提前致谢!

2 回答

  • 0

    这是我的实现:

    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));
        }
    }
    

    我们从MATLAB编译并调用MEX函数:

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

    如您所见,这将创建长度为10的structure array . 例如,第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
    
  • 4

    我看到两个问题(不一定完整):

    • out 在代码中创建为标量结构,而应该是

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

    • 您指定 const char *fields[] = {"start", "end","depth"}; ,但之后尝试设置 lenght 字段 .

    第一个问题可能是您观察的原因 - 在mex中,您必须适当地预分配结构矩阵 .

相关问题