2016-11-15 9 views
1

Я пытаюсь построить файл MEX для вызова команды Lapack slasd4 в MATLAB. Построение файла mex завершается успешно, но когда я пытаюсь использовать команду, он сбрасывает MATLAB и заканчивается сообщениемУстранение прерывания доступа вызов slasd4 mex

Аномальное прерывание: нарушение доступа.

Может ли кто-нибудь помочь мне решить эту проблему? Я использую 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

Я не знаю, что нормальная подпись в C для ' slasd4', но тот факт, что вы передаете его только указатели, уже поражает меня как нечетное ... –

+0

Кроме того, 'n' является неподписанным (' mwSize'), 'i' подписан (' mwSignedIndex'), что является нечетным , Более того, вы не можете указывать указатели на 'mxArrays' в' mwSignedIndex', чтобы получить их размеры ... Не хотите ли вы называть 'mxGetN()'? –

+0

Можете ли вы предоставить ссылку на какую-то документацию на 'slasd4', используемую в этом контексте? –

ответ

0

Несколько проблем, связанных с типы данных и т. д. Все целые переменные, используемые для вызовов BLAS и LAPACK с использованием библиотек, поставляемых MATLAB sh ould обычно вводится как mwSignedIndex, а не mwSize. Кроме того, если базовый тип данных передаваемых переменных удваивается, вы не можете магически изменить эти данные для плавания, просто указав на них (float *). Поэтому вам нужно убедиться, что входные данные являются правильным классом. Впереди, вы должны положить в много больше проверки для переменного класса и размера и т.д. Вот код, с дополнительными проверками авансовых, вместе с парой исправлений коды:

#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 

Я только сделал достаточно изменений, чтобы вы прошли через сегрегацию. Я не проверял ничего о самом фактическом вызове функции, чтобы убедиться, что у вас есть правильные размеры для рабочей переменной или что переменные имеют соответствующие данные и т. Д.