【问题标题】:Error of mexfunction variables in an array of a structure variable结构变量数组中的 mexfunction 变量错误
【发布时间】:2014-12-19 05:29:59
【问题描述】:

最近,我尝试使用结构变量编写 mexfunctions。 我观看了教程,但由于变量值的传递方式而感到困惑。 以下示例 (mexfunction_using_ex_wrong.m & mexfunction_using_ex_wrong.cpp) 演示了如何在 mexfunction 中获取从 matlab 传递的变量。 但是,在这种情况下,结果是:

address i_c1=2067094464 i_c2=2067094464
        i_c1=10         i_c2=10
address i_c1=1327990656 i_c2=2067100736
        i_c1=2          i_c2=20
address i_c1=2067101056 i_c2=2067063424
        i_c1=3          i_c2=30

可以看出,结构变量的 c1 & c2 数组的第一个元素意外地相同。

但是,在另一个示例 (mexfunction_using_ex_correct.m & mexfunction_using_ex_correct.cpp) 中,结构变量的数组 1 (b1) 和数组 2(b2) 的元素是不相关的,正如我所料。 结果是:

address i_b1=1978456576 i_b2=1326968576
        i_b1=1          i_b2=10
address i_b1=1978456584 i_b2=1326968584
        i_b1=2          i_b2=20
address i_b1=1978456592 i_b2=1326968592
        i_b1=3          i_b2=30

但是,在编程中使用第一个示例更为常见。那么有人可以解释为什么在第一个示例中 i_c1 和 i_c2 的地址相同吗?

下面的代码是mexfunction_using_ex_wrong.m

clc
clear all
close all

mex mexfunction_using_ex_c_wrong.cpp;

a.b(1).c1=double(1);
a.b(2).c1=double(2);
a.b(3).c1=double(3);

a.b(1).c2=double(1);
a.b(2).c2=double(2);
a.b(3).c2=double(3);

mexfunction_using_ex_c_wrong(a);

下面的代码是mexfunction_using_ex_c_wrong.cpp

#include "mex.h"

void mexFunction(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[]) 
{   
     int i, j, k;

     double *i_c1;
     double *i_c2;

     // for struct variables(pointers) inside fcwcontext
     mxArray *mx_b, *mx_c1, *mx_c2;    

     mx_b=mxGetField(prhs[0], 0, "b");

    for(i = 0;i < 3;i=i+1)
    {               
        mx_c1=mxGetField(mx_b, i, "c1");
        mx_c2=mxGetField(mx_b, i, "c2");

        i_c1=mxGetPr(mx_c1);
        i_c2=mxGetPr(mx_c2);        

        *i_c2=(*i_c2)*10;

        printf("address i_c1=%d i_c2=%d\n", i_c1, i_c2);
        printf(" i_c1=%g i_c2=%g\n", *i_c1, *i_c2);               
    }                  
}

下面的代码是mexfunction_using_ex_c_correct.m

clc
clear all
close all

mex mexfunction_using_ex_correct.cpp;

a.b1(1)=double(1);
a.b1(2)=double(2);
a.b1(3)=double(3);

a.b2(1)=double(1);
a.b2(2)=double(2);
a.b2(3)=double(3);

mexfunction_using_ex_correct(a);

下面的代码是mexfunction_using_ex_c_correct.cpp

#include "mex.h"

void mexFunction(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[]) 
{   
     int i, j, k;

     double *i_b1;
     double *i_b2;

     mxArray *mx_b1, *mx_b2;    

     mx_b1=mxGetField(prhs[0], 0, "b1");
     mx_b2=mxGetField(prhs[0], 0, "b2");

    for(i = 0;i < 3;i=i+1)
    {                       
        i_b1=mxGetPr(mx_b1);
        i_b2=mxGetPr(mx_b2);        

        i_b2[i]=i_b2[i]*10;

        printf("address i_b1=%d i_b2=%d\n", &i_b1[i], &i_b2[i]);
        printf(" i_b1=%g i_b2=%g\n", i_b1[i], i_b2[i]);                
    }                  
}

【问题讨论】:

    标签: c matlab mex


    【解决方案1】:

    由于 MATLAB 的内部写入时复制优化,地址不是“意外相同” - 它们是有意相同的。如果您查看 MEX 文档,您会看到分散在各处的警告...

    Do not modify any prhs values in your MEX-file. Changing the data in these read-only mxArrays can produce undesired side effects.

    ...以各种形式...

    Note Inputs to a MEX-file are constant read-only mxArrays. Do not modify the inputs. Using mxSetCell* or mxSetField* functions to modify the cells or fields of a MATLAB® argument causes unpredictable results.

    ...试图明确说明您应该绝对不要修改您收到的任何输入内容。通过在输入数据上调用 mxGetPr() 并像使用 i_b2i_c2 一样写回该指针,您将直接进入“不可预测的结果”领域 - 如果您查看 MATLAB 工作区中的 a.b(1).c1通话后,即使您“仅”更改了c2,它也确实是10。

    在 MEX 中,您在不了解或无法访问 MATLAB 内部管理的情况下查看原始数据存储,因此修改任何内容的唯一安全方法是使用mxCreate*mxDuplicate* 函数来获取您自己的安全数​​组,然后您可以做任何您想做的事情,并通过 plhs 传回 MATLAB。

    也就是说,我承认我曾滥用in-place modification 来获得显着的性能提升,在这种情况下我可以保证我的数据是唯一且不共享的,但它充其量是不受支持的,最坏的情况是完全危险的。

    【讨论】:

    • 感谢您的回复。我终于解决了这个问题。 The answer 用一个非常有用的函数 mxCreateSharedDataCopy() 完全解决了我的问题。但是,此函数是一个未记录的函数,只有在文件为 .c 时才能在 Matlab 2014 中调用。如果该文件是 .cpp,则链接器找不到它。错误信息是error LNK2019: external symbol unresolved "struct mxArray_tag * __cdecl mxCreateSharedDataCopy(struct mxArray_tag const *)"。
    • 我真的,强烈建议不要这样做 - 使用 mxDuplicateArray,修改 那个 副本,然后通过 plhs 将其传回。了解如何正确使用 MEX 并熟悉它,然后再考虑涉足不受支持的黑客攻击和未记录的实施细节。如果(在我的情况下)hack 在开发过程中每天为您节省大约一个半小时的运行时间,那么也许值得冒险;对于学习来说,这是一个糟糕的主意。
    猜你喜欢
    • 2018-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-18
    • 1970-01-01
    相关资源
    最近更新 更多