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.