Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29274 Discussions

Passing external subroutines to a DLL

OP1
New Contributor III
554 Views
Hi,

I am struggling with the following problem. I have a DLL subroutine DLL_SUB which has (as a dummy argument) an external subroutine EXT_SUB. When called by the main program unit, the role of DLL_SUB is to store in a DLL module the address of EXT_SUB, so thatEXT_SUB can be accessed andcalled by other subroutines of the DLLwithout having to be passed as a dummy argument.

How can I achieve this with IVF 10? The goal is to have the calling units initialize the DLL witha specificsubroutine, which will be internally used by all subsequent calls to the DLL subroutines, without having to specify this external subroutine as a dummy argument.

I hope I explained this intelligibly.

Thanks,

Olivier
0 Kudos
2 Replies
OP1
New Contributor III
554 Views

My apologies - I just found a way to solve this problem. The best way to solve a problem is oftento enunciate it clearly :)
I include below a pseudo code illustrating what I wanted to achieve - hopefully this will be helpful to some!

Olivier

[fortran]!***
!*** Here are the program units defined in the DLL.
!***

MODULE DLL_MODULE
    IMPLICIT NONE
    INTERFACE
        SUBROUTINE INTERNAL_SUB(I)
            INTEGER,INTENT(IN) :: I
        END SUBROUTINE INTERNAL_SUB
    END INTERFACE
    INTEGER(KIND=INT_PTR_KIND()) :: INTERNAL_SUB_POINTER
    POINTER(INTERNAL_SUB_POINTER,INTERNAL_SUB)
END MODULE DLL_MODULE

SUBROUTINE DLL_SELECT_SUBROUTINE(SUB)
!DEC$ ATTRIBUTES DLLEXPORT :: DLL_SELECT_SUBROUTINE
    USE DLL_MODULE
    IMPLICIT NONE
    INTERFACE
        SUBROUTINE SUB(I)
            INTEGER,INTENT(IN) :: I
        END SUBROUTINE SUB
    END INTERFACE
    INTERNAL_SUB_POINTER = LOC(SUB)
END SUBROUTINE DLL_SELECT_SUBROUTINE

SUBROUTINE DLL_GENERIC_SUB(I)
!DEC$ ATTRIBUTES DLLEXPORT :: DLL_GENERIC_SUB
    USE DLL_MODULE
    IMPLICIT NONE
    INTEGER,INTENT(IN) :: I
    CALL INTERNAL_SUB(I)
END SUBROUTINE DLL_GENERIC_SUB

!***
!*** Here are the program units defined in the main program.
!***

SUBROUTINE A(I)
    IMPLICIT NONE
    INTEGER,INTENT(IN) :: I
    WRITE(*,*) I+1
END SUBROUTINE A

SUBROUTINE B(I)
    IMPLICIT NONE
    INTEGER,INTENT(IN) :: I
    WRITE(*,*) I+2
END SUBROUTINE B

PROGRAM MAIN
    USE DLL_MODULE
    IMPLICIT NONE
    INTEGER I
    EXTERNAL A,B
    I = 1
    CALL DLL_SELECT_SUBROUTINE(A)
    CALL DLL_GENERIC_SUB(I)
    CALL DLL_SELECT_SUBROUTINE(B)
    CALL DLL_GENERIC_SUB(I)
END PROGRAM MAIN[/fortran]

0 Kudos
mecej4
Honored Contributor III
554 Views
What you want, if I read your note correctly and if a standard-compliant solution is preferred, is to store the value of EXT_SUB into a variable in the DLL, of type procedure-pointer.

Such variables are available in Fortran 2003 but not in earlier versions. Look up procedure-pointer in the IFort documentation.
0 Kudos
Reply