我正在与MEX合作并获得奇怪的行为,我将其分离到以下非常简单的程序:
#include "mex.h"
#include <stdio.h>
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
double *A;
int i;
if ( nrhs != 1
|| nlhs > 1
|| !mxIsDouble(prhs[0])
|| mxIsComplex(prhs[0])
|| mxGetM(prhs[0])!=1
) mexErrMsgTxt("internal error: dtimes2: input error");
A = mxGetPr(prhs[0]);
for (i=0; i<3; i++) A[i] *= 2;
return; }
Run Code Online (Sandbox Code Playgroud)
所以问题是这样的:在MATLAB会话中,
B=[3.2,5.6,9.4]; dtimes2(B); B
Run Code Online (Sandbox Code Playgroud)
和MATLAB说:B = 6.4000 11.2000 18.8000
到现在为止还挺好.但现在:
B=[3.2,5.6,9.4]
Run Code Online (Sandbox Code Playgroud)
和MATLAB说:B = 6.4000 11.2000 18.8000
但是当我说
B=[-34.5,-57.6,-28.9]
Run Code Online (Sandbox Code Playgroud)
然后MATLAB说:B = -34.5000 -57.6000 -28.9000
你看到中间我不能重新分配B,如果数字与以前相同.所以,现实检查:
A=[1,2,3]; A=2*A; A=[1,2,3]
Run Code Online (Sandbox Code Playgroud)
当然有效:MATLAB最后说A = [1,2,3].
MEX警告说我的编译器是'6.2.1-2',但支持的编译器是'4.7.x',但对于这个简单的程序我几乎没想到会出现问题.这里出了什么问题?
您不应该修改进入MEX包装器的任何输入.这是未定义的行为,这就是您的MEX函数中发生的事情.MEX建议您返回输出而不是改变输入.如果您真的希望改变输入或他称之为就地编辑,您可以在Yair Altman的未记载的MATLAB博客中阅读更多相关信息.当你开始使用MEX时,我不鼓励这种行为.虽然有些情况值得,但除非你知道自己在做什么,否则请尽量避免:http://undocumentedmatlab.com/blog/matlab-mex-in-place-editing.
至于不修改输入,这在mexFunction网关的函数声明中明确定义:
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
^^^^^^^^^^^^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)
该const修改确保没有输入指针的改变,这是很好的......但是,这并不从实际修改的内存指针指的还是这样的内容,你停在原地.一般而言,由于"惰性复制"行为,您为MATLAB工作空间中的任何MATLAB变量创建的内存可能与其他MATLAB变量共享.因此,您在矩阵,矢量或单个值中看到的值可能会链接到其他矩阵,向量或其他变量的单个值.当您在原地更改内存时,您也会更改其他变量,这可能是您看到不一致行为的原因.
始终返回实际所需的输出而不是改变输入,因为您将保证获得正确的结果.我已修改下面的代码,以便输出新的矩阵而不是就地执行计算.
#include "mex.h"
#include <stdio.h>
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
double *A;
double *B; // Change - For the output
int i;
if ( nrhs != 1
|| nlhs > 1
|| !mxIsDouble(prhs[0])
|| mxIsComplex(prhs[0])
|| mxGetM(prhs[0])!=1
) mexErrMsgTxt("internal error: dtimes2: input error");
A = mxGetPr(prhs[0]);
// Change - Create output memory
mwSize rows = mxGetM(prhs[0]);
mwSize cols = mxGetN(prhs[0]);
plhs[0] = mxCreateDoubleMatrix(rows, cols, mxREAL);
// Change - get a pointer to the output memory
B = mxGetPr(plhs[0]);
for (i=0; i<3; i++) B[i] = 2*A[i]; // Change - Write to output memory
return;
}
Run Code Online (Sandbox Code Playgroud)
然后你会这样做:
B = dtimes2(B);
Run Code Online (Sandbox Code Playgroud)