Search code examples
fortranfortran90intel-fortranstdcallcdecl

Call a StdCall Subroutine in Fortran


I have two subroutines in a DLL. To call them in C#, they are changed to STDCALL like this:

    SUBROUTINE MoveToZero(X, N)
    !DEC$ ATTRIBUTES DLLEXPORT::MoveToZero
    !DEC$ ATTRIBUTES STDCALL,ALIAS:'RemoveBias'::MoveToZero
    USE MKL_DFTI
    INTEGER :: N
    DOUBLE PRECISION :: X(N)
    DOUBLE COMPLEX :: Y(N / 2 + 1)
    type(DFTI_DESCRIPTOR), POINTER :: des
    status = DftiCreateDescriptor(des, DFTI_DOUBLE, DFTI_REAL, 1, N)
    status = DftiSetValue(des, DFTI_PLACEMENT, DFTI_NOT_INPLACE)
    status = DftiCommitDescriptor(des)
    status = DftiComputeForward(des, X, Y)
    Y(1) = 0
    status = DftiComputeBackward(des, Y, X)
    status = DftiFreeDescriptor(des)
    X = X / N
    END

    SUBROUTINE GetApparent(current, voltage, N, output)
    !DEC$ ATTRIBUTES DLLEXPORT::GetApparent
    !DEC$ ATTRIBUTES STDCALL,ALIAS:'GetApparent'::GetApparent
    INTEGER :: N
    INTEGER ,PARAMETER :: M = 5
    DOUBLE PRECISION :: current(N), voltage(N)
    DOUBLE PRECISION :: output(M) 

    CALL MoveToZero(current, size(current)) !   This line raise an error
    End

Like this, I also need to call MoveToZero in GetApparent, but there is an error:

1>D:\Integrate\ProcessModule\Source1.f90(29): error #7519: 
  Required explicit interface for a procedure with C or STDCALL 
  attribute is missing from original source.   [MOVETOZERO]

So, how to call a stdcall subroutine in Fortran?


Solution

  • I can't say for C#, but the problem here is that you call, in Fortran, a stdcall subroutine without declaring its interface: CALL MoveToZero(x, size(x)).

    You have to declare the MoveToZero's interface in the body of GetApparent, which can be done with an interface block for instance:

    SUBROUTINE GetApparent(current, voltage, N, output)
    !DEC$ ATTRIBUTES DLLEXPORT::GetApparent
    !DEC$ ATTRIBUTES STDCALL,ALIAS:'GetApparent'::GetApparent
    
    
    INTERFACE
        SUBROUTINE MoveToZero(X, N)
        !DEC$ ATTRIBUTES DLLEXPORT::MoveToZero
        !DEC$ ATTRIBUTES STDCALL,ALIAS:'RemoveBias'::MoveToZero
    
        !**** Declare type of X and N ****
    
        END SUBROUTINE
    END INTERFACE
    
    !...Some Codes
    
    CALL MoveToZero(n, n)
    
    !...Some Codes
    
    END
    

    You may also use an interface module (i.e. a module with only those interface blocks) and USE it in all procedures that need these declarations.