在 Fortran 中调用 StdCall 子例程

Call a StdCall Subroutine in Fortran

我在一个 DLL 中有两个子例程。要在 C# 中调用它们,将它们更改为 STDCALL,如下所示:

    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

像这样,我也需要在GetApparent中调用MoveToZero,但是出现错误:

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]

那么,如何在 Fortran 中调用 stdcall 子例程?

我不能说 C#,但这里的问题是你在 Fortran 中调用了一个 stdcall 子例程而不声明它的接口:CALL MoveToZero(x, size(x)).

您必须在 GetApparent 的主体中声明 MoveToZero 的接口,例如可以使用接口块来完成:

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

您也可以使用接口模块(即只有那些接口块的模块)并在需要这些声明的所有过程中使用它。