Почему объявленный и заполненный mwSize спасает день, когда константа не - PullRequest
0 голосов
/ 11 мая 2019

У меня есть эта подпрограмма:

    subroutine FotranDgemmMatrixMultiplication(A, B, C, m, n, p, mkl)
        integer m, n, p
        real*8 mkl
        real*8 A(m,n), B(n,p), C(m,p)
        if (mkl .ne. 1) then
            C = matmul(A,B)
        else
            C = matmul(B,A)
        endif
    end

, которую я использую в файле mex gateway следующим образом:

#include <fintrf.h>
C     The gateway routine
    subroutine mexFunction(nlhs, plhs, nrhs, prhs)

    implicit none
    mwPointer mxGetM, mxGetN, mxIsNumeric, mxIsLogical
    mwPointer mxCreateDoubleMatrix
    mwPointer plhs(*), prhs(*)
    mwPointer A_pr, B_pr, C_pr, mkl_pr
    mwPointer mxGetPr
    integer nlhs, nrhs
    real*8, allocatable, dimension(:,:) :: x, y, z
    real*8 mkl
    mwSize m, n, p, q, r, s
    mwSize size1, size2, size3

C     Check for proper number of arguments. 
    if (nrhs .ne. 3) then
        call mexErrMsgTxt('Three inputs required.')
    elseif (nlhs .ne. 1) then
        call mexErrMsgTxt('One output required.')
    endif

C     Check to see both inputs are numeric.
    if (mxIsNumeric(prhs(1)) .ne. 1) then
        call mexErrMsgTxt('Input #1 is not a numeric array.')
    elseif (mxIsNumeric(prhs(2)) .ne. 1) then
        call mexErrMsgTxt('Input #2 is not a numeric array.')
    elseif (mxIsNumeric(prhs(3)) .ne. 1) then
        call mexErrMsgTxt('Input #3 is not a numeric array.')
    endif

C     Get the size of the input matrix #1.
    m = mxGetM(prhs(1))
    n = mxGetN(prhs(1))

C     Get the size of the input matrix #2.
    p = mxGetM(prhs(2))
    q = mxGetN(prhs(2))

C     Check that the sizes are compatible for a matrix product
    if (n .ne. p) then
        call mexErrMsgTxt('nbcol1 should be equal to nbrow2.')
    endif

    size1 = m*n
    size2 = p*q

C     Check that the input #3 is a scalar
    r = mxGetM(prhs(3))
    s = mxGetN(prhs(3))
    if(r .ne. 1 .or. s .ne. 1) then
        call mexErrMsgTxt('Input #3 is not a scalar.')
    endif

C     Create matrix for the return argument.
    plhs(1) = mxCreateDoubleMatrix(m, q, 0)
    A_pr = mxGetPr(prhs(1))
    B_pr = mxGetPr(prhs(2))
    mkl_pr = mxGetPr(prhs(3))
    C_pr = mxGetPr(plhs(1))

    allocate( x(m,n), y(p,q), z(m,q) )

C     Load the data into Fortran arrays.
    call mxCopyPtrToReal8(A_pr, x, size1)
    call mxCopyPtrToReal8(B_pr, y, size2)
    call mxCopyPtrToReal8(mkl_pr, mkl, 1) ! suspicious line

C     Call the computational subroutine.
    call FotranDgemmMatrixMultiplication(x, y, z, m, n, q, mkl) ! crash here

C     Load the output into a MATLAB array.
    size3 = m*q
    call mxCopyReal8ToPtr(z, C_pr, size3)

    !deallocate(x,y,z)

    return
    end

, которая выполняется так, как задумано при отладке, но при сбое при выпускесбой в строке:

    call FotranDgemmMatrixMultiplication(x, y, z, m, n, q, mkl)

Если я добавлю mwSize sizeOne на sizeOne = 1 и заменим подозрительную строку (см. код) на:

    call mxCopyPtrToReal8(mkl_pr, mkl, sizeOne)

, то сбой не произойдетбольше не происходит.Я не понимаю, что происходит, поскольку в x64 «тип» mwSize определяется (в fintrf.h) как mwpointer, что само по себе определяется как integer*4, что должно относиться к «константе» 1 правильно нормально.

...