我正在尝试构建一个MEX文件来调用MATLAB中的Lapack命令slasd4
。构建mex文件成功,但是当我尝试使用该命令时,它会崩溃MATLAB并以消息结束
异常终止:访问冲突。
有人可以帮我解决这个问题吗?我正在使用带有内置插件的MATLAB R2016b来使用MEX文件。
这是我的mex文件:
#include "mex.h"
#include "lapack.h"
void mexFunction(int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
{
mwSize n, i, info = 0;
float *z, *d, *delta, *work, *sigma, rho;
/* verify input/output arguments */
if (nrhs > 4) {
mexErrMsgTxt("Too many input arguments.");
}
if (nlhs > 3) {
mexErrMsgTxt("Too many output arguments.");
}
/* dimensions of input matrix */
n = mxGetN(prhs[0]);
/* create output matrices */
plhs[0] = mxCreateNumericMatrix(n, 1, mxSINGLE_CLASS, mxREAL);
plhs[1] = mxCreateNumericMatrix(n, 1, mxSINGLE_CLASS, mxREAL);
plhs[2] = mxCreateNumericMatrix(1, 1, mxSINGLE_CLASS, mxREAL);
/* get pointers to data */
i = (mwSignedIndex) prhs[3];
d = (float *) mxGetPr(prhs[0]);
z = (float *) mxGetPr(prhs[1]);
rho = (float) mxGetScalar(prhs[2]);
delta = (float *) mxGetPr(plhs[0]);
work = (float *) mxGetPr(plhs[1]);
sigma = (float *) mxGetPr(plhs[2]);
/* Call Lapack function */
slasd4(&n, &i, d, z, delta, &rho, sigma, work, &info);
/* check if call was successful */
if (info < 0) {
mexErrMsgTxt("Illegal values in arguments.");
} else if (info > 0) {
mexErrMsgTxt("Failed to converge.");
}
}
这是一个简单的测试示例:
D = [2; 0];
z = [1;0];
[delta, work, sigma] = slasd4(D,z,-1,1);
这是故障的起始堆栈跟踪:
[ 0] 0x000000000b8c15b0 C:\Users\Joni\Desktop\NLA\Paper\slasd4.mexw64+00005552 mexfilerequiredapiversion+00000032
[ 1] 0x000000000b8c1561 C:\Users\Joni\Desktop\NLA\Paper\slasd4.mexw64+00005473 mexFunction+00000305
[ 2] 0x00000000fc5fc5d1 C:\Program Files\MATLAB\R2016b\bin\win64\libmex.dll+00116177 mexRunMexFile+00000129
[ 3] 0x00000000fc5fb2e2 C:\Program Files\MATLAB\R2016b\bin\win64\libmex.dll+00111330 mexFeature_mexver+00001794
[ 4] 0x00000000fc5fa506 C:\Program Files\MATLAB\R2016b\bin\win64\libmex.dll+00107782 mexUnlock+00020182
答案 0 :(得分:0)
与数据类型等相关的几个问题。使用MATLAB提供的库的BLAS和LAPACK调用所使用的所有整数变量通常应该键入mwSignedIndex,而不是mwSize。此外,如果传入的变量的基础数据类型是双精度数,那么只需将(浮点数)指向它们,就不能神奇地将数据更改为浮点数。因此,您需要确保输入数据是正确的类。在前面,您应该对批次进行更多检查,以获取变量类和大小等。以下是一些带有额外前期检查的代码,以及一些代码更正:
#include "mex.h"
#include "lapack.h"
void mexFunction(int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
{
mwSignedIndex n, i, info = 0; /* CHANGED */
float *z, *d, *delta, *work, *sigma, rho;
mxArray *plhs0, *plhs1, *plhs2; /* NEW */
/* verify input/output arguments */
if (nrhs != 4) { /* CHANGED */
mexErrMsgTxt("Need exactly 4 inputs."); /* CHANGED */
}
if (nlhs > 3) {
mexErrMsgTxt("Too many output arguments.");
}
/* NEW */
if( !mxIsSingle(prhs[0]) || mxIsComplex(prhs[0]) ) {
mexErrMsgTxt("1st argument must be a real single class variable");
}
if( !mxIsSingle(prhs[1]) || mxIsComplex(prhs[1]) ) {
mexErrMsgTxt("2nd argument must be a real single class variable");
}
if( !mxIsNumeric(prhs[2]) || mxIsComplex(prhs[2]) || mxGetNumberOfElements(prhs[2]) != 1 ) {
mexErrMsgTxt("3rd argument must be a real numeric scalar variable");
}
if( !mxIsNumeric(prhs[3]) || mxIsComplex(prhs[3]) || mxGetNumberOfElements(prhs[3]) != 1 ) {
mexErrMsgTxt("4th argument must be a real numeric scalar variable");
}
/* dimensions of input matrix */
n = mxGetN(prhs[0]);
/* create output matrices */
plhs0 = mxCreateNumericMatrix(n, 1, mxSINGLE_CLASS, mxREAL); /* CHANGED */
plhs1 = mxCreateNumericMatrix(n, 1, mxSINGLE_CLASS, mxREAL); /* CHANGED */
plhs2 = mxCreateNumericMatrix(1, 1, mxSINGLE_CLASS, mxREAL); /* CHANGED */
/* get pointers to data */
i = (mwSignedIndex) mxGetScalar(prhs[3]); /* CHANGED */
d = (float *) mxGetData(prhs[0]); /* CHANGED */
z = (float *) mxGetData(prhs[1]); /* CHANGED */
rho = (float) mxGetScalar(prhs[2]);
delta = (float *) mxGetData(plhs0); /* CHANGED */
work = (float *) mxGetData(plhs1); /* CHANGED */
sigma = (float *) mxGetData(plhs2); /* CHANGED */
/* Call Lapack function */
slasd4(&n, &i, d, z, delta, &rho, sigma, work, &info);
/* check if call was successful */
if (info < 0) {
mexErrMsgTxt("Illegal values in arguments.");
} else if (info > 0) {
mexErrMsgTxt("Failed to converge.");
}
plhs[0] = plhs0; /* NEW */
if( nlhs > 1 ) plhs[1] = plhs1; /* NEW */
if( nlhs > 2 ) plhs[2] = plhs2; /* NEW */
}
这是跑步的结果:
>> D = [2; 0];
>> z = [1;0];
>> [delta, work, sigma] = slasd4(D,z,-1,1)
??? Error using ==> slasd4
1st argument must be a real single class variable
>> [delta, work, sigma] = slasd4(single(D),z,-1,1)
??? Error using ==> slasd4
2nd argument must be a real single class variable
>> [delta, work, sigma] = slasd4(single(D),single(z),-1,1)
delta =
1
work =
1
sigma =
1.7321
我只做了足够的改动让你超越了seg的错误。我没有检查实际函数调用本身的任何内容,以确保您具有工作变量的正确尺寸,或者变量具有适当的数据等。