2014-12-19 62 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