2014-12-19 66 views
3

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

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

回答

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.

...试图说清楚,你应该绝对不能修改任何你rec即作为输入。通过在输入数据上调用mxGetPr()并将其写回到与i_b2i_c2相同的那个指针,您将进入“不可预知的结果”领域 - 如果在调用之后在MATLAB工作区中查看a.b(1).c1,它会真的即使你“只”改变了c2也是10。

从墨西哥,你看原始数据存储而没有任何知识,或访问,MATLAB的内部处理,所以任何修改的唯一安全方式是使用mxCreate*mxDuplicate*功能,让您的自己的安全阵列,然后你可以做任何你想要的,并通过plhs传回MATLAB。

也就是说,我承认在一次我可以保证我的数据是唯一的和未共享的情况下滥用in-place modification以获得显着的性能提升,但最多是不受支持的,最坏的情况是非常危险。

+2

谢谢您的回复。我终于解决了这个问题。 [答案](http://www.mathworks.com/matlabcentral/answers/uploaded_files/1487/mxsharedcopy.c)用一个非常有用的函数 mxCreateSharedDataCopy()完全解决了我的问题。但是,这个函数是一个未公开的函数,如果文件是.c,只能在Matlab 2014中调用。如果该文件是.cpp,则链接程序找不到它。错误消息是错误LNK2019:外部符号未解析“struct mxArray_tag * __cdecl mxCreateSharedDataCopy(struct mxArray_tag const *)”。 – 2014-12-25 05:37:21

+0

我真的很**强烈推荐不要这样做 - 使用'mxDuplicateArray',修改_that_ copy,然后通过'plhs'传回。学习如何使用MEX _properly_,并在考虑涉及不支持的黑客攻击和未公开的实现细节之前,熟悉它。如果(和我一样)黑客在开发过程中每天节省大约一个半小时的运行时间,那么也许值得冒这个风险;为了学习,这是一个可怕的想法。 – Notlikethat 2014-12-25 10:29:17