避免使用mexCallMATLAB时复制数组
我已经写了一个MATLAB MEX文件。它调用MATLAB PINV
函数来计算摩尔彭罗斯伪逆。我命名这个功能 my_pinv
。 my_pinv
得到一个数组,并返回其伪逆,正是类似 PINV
:
I have written a mex file for MATLAB. It calls MATLAB pinv
function to calculate the Moore Penrose pseudoinverse. I named this function my_pinv
. my_pinv
gets an array and returns its pseudoinverse, exactly similar to pinv
:
A = magic(8); A = A(:,1:6)
b = 260*ones(8,1)
x = my_pinv(A)*b
在MEX文件,但是,我必须复制输入数组的值可以使用 mexCallMATLAB
。这里的内容 my_pinv.cpp
:
In the mex file, however, I have to copy the values of the input array to be able to use mexCallMATLAB
. Here is the content of my_pinv.cpp
:
#include <matrix.h>
#include <mex.h>
#include <string.h>
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
#define PRHS_A prhs[0]
#define PLHS_X plhs[0]
int M = mxGetM( PRHS_A ); // Get the dimensions of A.
int N = mxGetN( PRHS_A );
double *A_ptr = mxGetPr( PRHS_A );
mxArray *PINV_A = mxCreateDoubleMatrix(M, N, mxREAL); /* Put input in an mxArray */
memcpy(mxGetPr(PINV_A), A_ptr, sizeof(double)*M*N);
PLHS_X = mxCreateDoubleMatrix(N, M, mxREAL); // Create the output matrix.
mexCallMATLAB(1, &PLHS_X, 1, &PINV_A, "pinv");
}
反正是有,我跳过使用的memcpy
并直接使用输入数组, prhs [0]
,在 mexCallMATLAB
?我其实不喜欢需要,特别是当输入数组是非常大的要复制输入数组的值的事实。
Is there anyway that I skip using memcpy
and directly use the input array, prhs[0]
, in mexCallMATLAB
? I actually don't like the fact that the values of input array needs to be copied especially when the input array is very large.
其实,我想能够使用像
mexCallMATLAB(1, &PLHS_X, 1, &RHS_A, "pinv"); // (I know it is not right and the compiler would not like it but it is for the sake of example)
而不是
mexCallMATLAB(1, &PLHS_X, 1, &PINV_A, "pinv");
有人能分享在这方面他/她的经历?
Could someone share his/her experiences in this regard?
mexCallMATLAB
具有以下签名:
int mexCallMATLAB(int nlhs, mxArray *plhs[], int nrhs,
mxArray *prhs[], const char *functionName);
有关某种原因,RHS数组没有标记常量
预选赛。我不知道为什么......这解释了为什么你会得到一个编译错误:
For some reason, the RHS array is not marked with the const
qualifier. I dont know why... This explains why you get a compilation error:
// this is from Visual C++ 2013
error C2664: 'int mexCallMATLAB(int,mxArray*[],int,mxArray *[],const char *)' :
cannot convert argument 4 from 'const mxArray *[]' to 'mxArray *[]'
Conversion loses qualifiers
解决方案是明确地抛弃恒内斯告诉我们知道我们在做什么,编译器:
The solution is to explicitly cast away the constant-ness telling the compiler that we know what we're doing:
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
// validate arguments
if(nrhs != 1 || nlhs > 1)
mexErrMsgIdAndTxt("mex:error", "Wrong number of arguments.");
//perhaps do more validations here..
// out = pinv(in)
mexCallMATLAB(1, plhs, 1, const_cast<mxArray**>(prhs), "pinv");
}
在MATLAB
现在
Now in MATLAB:
>> x = rand(4,3);
>> my_pinv(x) - pinv(x)
ans =
0 0 0 0
0 0 0 0
0 0 0 0
如果由于某种原因,在某些情况下,墙角这证明有问题(我对此表示怀疑),更安全的方法是只使用复制数组:
If for some reason and in some corner case this proves problematic (I doubt it), the safer way is to just duplicate the array using:
mxArray *in = mxDuplicateArray(prhs[0]);
mexCallMATLAB(1, plhs, 1, &in, "pinv");
mxDestroyArray(in);
如果你绝对要避免产生深层副本,还有未公开的函数是创建一个共享的数据复制(其中只有创建一个新的数组头,但数据共享)。
If you absolutely want to avoid creating a deep copy, there are undocumented functions that create a shared-data copy (where only a new array header is created, but the data is shared).