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

Problem calling Fortran from C++ / iface change

ferrad01
Beginner
758 Views
We have a Fortran engine called from a C++ GUI. Up until now the engine was built with interface=CREF, as the GUI is built. However we are changing the engine to be built with iface=CVF, while keeping the GUI as CREF. I have written wrappers for the exported functions as follows (compiled with iface=CVF):

SUBROUTINE GETNAM1_CREF(DBNAME, MXLIS, NLIS, NAMLIS,
* FORMLIS, SYNLIS, PATH1)
!DEC$ATTRIBUTES DLLEXPORT, C, REFERENCE :: GETNAM1_CREF

IMPLICIT NONE
INTEGER MXLIS, NLIS
CHARACTER(LEN=*) PATH1
CHARACTER(LEN=*) DBNAME, NAMLIS(*), FORMLIS(*), SYNLIS(*)

CALL GETNAM1(DBNAME, MXLIS, NLIS, NAMLIS, FORMLIS, SYNLIS, PATH1)

RETURN
END

and in the DEF file:

EXPORTS
GETNAM1 = getnam1_cref

So the C++ code calls GETNAM1 as before, which gets redirected to GETNAM1_CREF via the DEF file. All is fine in the debugger in this function. However when I step into GETNAM1, the arguments are garbage.

Any idea what I'm doing wrong?
0 Kudos
3 Replies
jimdempseyatthecove
Honored Contributor III
759 Views
Show us your C++ function prototype?

I suspect you are passing some arguments by value (whereas the Fortran subroutine has by reference (pointer)).

Jim Dempsey
0 Kudos
ferrad01
Beginner
758 Views
Jim,

We compiled GETNAM1 in a lib with MIXED_STR_LENGTH (CVF) and it's linked to a DLL that contains GETNAM1_CREF which is compiled with CREF + NO_MIXED_STR_LENGTH. The C++ prototype is correct, the problem is when calling GETNAM1 from GETNAM1_CREF, it does not use the correct calling convention. Is this information not contained in the LIB? Or do I need to declare it for each subroutine in the LIB?

eg. adding the INTERFACE block below works:



[fxfortran]      SUBROUTINE GETNAM1_CREF(DBNAME, MXLIS, NLIS, NAMLIS,
     *                                FORMLIS, SYNLIS, PATH1)
      !DEC$ATTRIBUTES DLLEXPORT, C, REFERENCE :: GETNAM1_CREF

      IMPLICIT NONE

      INTERFACE 
        SUBROUTINE GETNAM1(DBNAME,MXLIS,NLIS,NAMLIS,FORMLIS,SYNLIS,
     &                     PATH1)
      !DEC$ATTRIBUTES MIXED_STR_LEN_ARG :: GETNAM1
          CHARACTER(*) :: DBNAME
          INTEGER(KIND=4) :: MXLIS
          INTEGER(KIND=4) :: NLIS
          CHARACTER(*) :: NAMLIS(*)
          CHARACTER(*) :: FORMLIS(*)
          CHARACTER(*) :: SYNLIS(*)
          CHARACTER(*) :: PATH1
        END SUBROUTINE GETNAM1
      END INTERFACE 


      INTEGER MXLIS, NLIS
      CHARACTER(LEN=*) PATH1
      CHARACTER(LEN=*) DBNAME, NAMLIS(*), FORMLIS(*), SYNLIS(*)

      CALL GETNAM1(DBNAME, MXLIS, NLIS, NAMLIS, FORMLIS, SYNLIS, PATH1)

      RETURN
      END
[/fxfortran]



0 Kudos
mecej4
Honored Contributor III
758 Views
Have you taken into account the stated order-of-precedence among declarations, directives and compiler-switches, as documented in the User Guide? If not, it can be confusing to change a lower-precedence item and then finding no consequent change in behavior.
0 Kudos
Reply