在 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
您也可以使用接口模块(即只有那些接口块的模块)并在需要这些声明的所有过程中使用它。
我在一个 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
您也可以使用接口模块(即只有那些接口块的模块)并在需要这些声明的所有过程中使用它。