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

Fortran linking error to C functions upgrading from 32 to 64 bit

Clark__Robert
Beginner
281 Views

I have the following two sample C functions: void rsub(...) and int sfunc(...)

Contents of rsub.c:

#include    "stdlib.h"
#include    "stdio.h"

void rsub(int iscalar, int icount){
    int        i;
    int        sum;

    printf("now in rsub()\n");
    printf("iscalar   =%d\n", iscalar);
    printf("icount    =%d\n", icount);

    sum = iscalar;
    sum += icount;

    printf("sum       =%d\n", sum);

    printf("leaving rsub()\n");
}

Contents of sfunc.c:

#include    "stdlib.h"
#include    "stdio.h"

int sfunc(int iscalar, int icount) {
    int        i;
    int        sum;

    printf("now in sfunc()\n");
    printf("iscalar   =%d\n", iscalar);
    printf("icount    =%d\n", icount);

    sum = iscalar;
    sum += icount;

    printf("leaving sfunc()\n");
    return(sum);
}

And they each have their respective FORTRAN interface modules:

contents of rlib_interface.for:

        MODULE rlib_interface
C       This  module specifies the FORTRAN interface for the S test.
        IMPLICIT NONE
        PRIVATE
        SAVE
C
          PUBLIC    rsub
C
        INTERFACE
C
            SUBROUTINE rsub( iscalar, icount )
                !DEC$ATTRIBUTES C, REFERENCE :: rsub
C
                INTENT( IN )              ::  iscalar
                INTENT( IN )              ::  icount
C
                INTEGER(KIND=4)           ::  iscalar
                !DEC$ATTRIBUTES VALUE     ::  iscalar
C
                INTEGER(KIND=4)           ::  icount
                !DEC$ATTRIBUTES VALUE     ::  icount
C
            END SUBROUTINE rsub
C
        END INTERFACE
C
        END MODULE rlib_interface

Contents of slib_interface.for:

       MODULE slib_interface
C       This  module specifies the FORTRAN interface for the S test.
        IMPLICIT NONE
        PRIVATE
        SAVE
C
          PUBLIC    sfunc
C
        INTERFACE
C
            FUNCTION sfunc( iscalar, icount )
                !DEC$ATTRIBUTES C, ALIAS:'_sfunc' :: sfunc
C
                INTEGER(KIND=4)           ::  sfunc
C
                INTENT( IN )              ::  iscalar
                INTENT( IN )              ::  icount
C
                INTEGER(KIND=4)           ::  iscalar
                !DEC$ATTRIBUTES VALUE     ::  iscalar
C
                INTEGER(KIND=4)           ::  icount
                !DEC$ATTRIBUTES VALUE     ::  icount
C
            END FUNCTION sfunc
C
        END INTERFACE
C
        END MODULE slib_interface

And I call them from FORTRAN programs R and S:

Contents of r.for:

    PROGRAM R
C     Test building in 32-bit mode and in 64-bit mode
C
      USE RLIB_INTERFACE
      INTEGER K/5/
C
      WRITE(6,6005)
 6005 FORMAT('Expected message from RSUB is 7')
C
      CALL RSUB(K, 2)
      END

Contents of s.for:

      PROGRAM S
C     Test building in 32-bit mode and in 64-bit mode
C
      USE SLIB_INTERFACE
      INTEGER K/5/
C
      WRITE(6,6005)
 6005 FORMAT('Expected return from SFUNC is 7')
C
      N = SFUNC(K, 2)
C  
      WRITE(6,6010)N
 6010 FORMAT('N=',I12)
 
      END

I run a file I call devenv32.bat to set up my 32-bit C/Fortran build environment in a DOS command window:

Contents of devenv32.bat:

set VSDIR=C:\Program Files (x86)\Microsoft Visual Studio 11.0
call "%VSDIR%\VC\BIN\VCVARS32.BAT"
echo setting IntelFTNDIR
set IntelFTNDIR=C:\Program Files (x86)\Intel\Composer XE 2013 SP1
echo calling ifortvars.bat
call "%IntelFTNDIR%"\bin\ifortvars.bat ia32 vs2012

I run rcomp.bat to compile r:

ifort -c /module:. /integer-size:32 /real-size:32 rlib_interface.for
ifort -c /module:. /integer-size:32 /real-size:32 r.for
cl -c  rsub.c

I run rbuild.bat to build r:

ifort /exe:r r.obj ^
rsub.obj

And similarly for scomp.bat:

ifort -c /module:. /integer-size:32 /real-size:32 slib_interface.for
ifort -c /module:. /integer-size:32 /real-size:32 s.for
cl -c sfunc.c

...and sbuild.bat:

ifort /exe:s s.obj ^
sfunc.obj

And then I run r:

Expected message from RSUB is 7
now in rsub()
iscalar   =5
icount    =2
sum       =7
leaving rsub()


And then I run s:

Expected return from SFUNC is 7
N=           7
now in sfunc()
iscalar   =5
icount    =2
leaving sfunc()


So far everything is exactly correct.

And then I start a new DOS window and attempt to shift gears to 64-bit compilation for both C and FORTRAN.

Contents of devenv64.bat:

set VSDIR=C:\Program Files (x86)\Microsoft Visual Studio 11.0
call "%VSDIR%\VC\vcvarsall" x86_amd64
echo setting IntelFTNDIR
set IntelFTNDIR=C:\Program Files (x86)\Intel\Composer XE 2013 SP1
echo calling ifortvars.bat
call "%IntelFTNDIR%"\bin\ifortvars.bat intel64 vs2012

R compiles, links, and runs great.

S however, having a function return type compiles, but then when I go to link in sbuild.bat I get the following error message:

C:\Users\ClarkBG\Desktop\Dexter\ToShip>ifort /exe:s s.obj sfunc.obj
Microsoft (R) Incremental Linker Version 11.00.61030.0
Copyright (C) Microsoft Corporation.  All rights reserved.

-out:s.exe
-subsystem:console
s.obj
sfunc.obj
s.obj : error LNK2019: unresolved external symbol _sfunc referenced in function MAIN__
s.exe : fatal error LNK1120: 1 unresolved externals

So...what's going on? 

  • Both R and S work fine in my 32-bit C/Fortran compile/link/run DOS environment.
  • R works fine in 64-bit too.
  • S compiles, but won't link in 64-bit.
  • The only functional differences between programs R and S are:
    • rsub.c returns void and is CALLed as a FORTRAN subroutine.
    • sfunc.c has an int return type and is used in-line as a FORTRAN function.

Is there a work-around for this?  This is a tiny example of the same issue I'm having while maintaining a much larger proprietary commercial code.

0 Kudos
1 Reply
IanH
Honored Contributor II
281 Views

Your Fortran code for the interface of sfunc explicitly sets the linker name of the procedure (its alias) to be `_sfunc`.  That name happens to match the conventions used by the 32 bit C compiler, but 64 bit conventions are different - there is no leading underscore.

Your `r` example works because there is no such specification of the linker name.

Delete the ALIAS:'_sfunc' attributes specification and things should work.

But I strongly recommend that you use the C-interoperability features of the Fortran 2003 standard instead of the !DEC$ ATTRIBUTES stuff.

0 Kudos
Reply