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

Changing mxing language code to compile and link on 64 and 32-bits

van_der_merwe__ben
New Contributor II
617 Views
Hi, I have some code that I would like to compile in 32 and 64-bits (same general compile flags). Flipping pure Fortran code from 32 to 64 bits works and runs fine. But the issues is when mixing C/C++/Fortran code. I am already using /4I4 to ensure the same integer size. Consider two examples which compile fine with 32 bits but give link errors in 64 bits:

Example 1:

Fortran code:

!dec$ attributes alias:'__clearfp' :: clearfp

call clearfp

Links fine in 32-bits, but in 64-bits (linking against the exact equivalent 64-bit runtime libraries) you get and unresolved external __clearfp.

Tried removing the !dec$ or removing the __ or changing it, but no luck yet. Likely the solution is obvious, but it still eludes me. (This is a .FOR file, not .F90).

Dumpbin says the 32-bit dll imports _clearfp from MSVCR80D.dll, and MSVCR80D.dll in 64-bit also exports _clearfp. So why does the 64-bit Fortran not find it? I checked and both are set to link against the default and correct and same version libraries. The 64-bit Fortran obj says it wants to import __clearfp, and the 32-bit obj also says the same thing. That suggests the 64-bit link is not linking against MSVCR80d, except I can find no evidence of that, it is set to link against the default libraries? Mmm.

Ok, in 64-bits, changing the alias from '__cleafp' to '_clearfp' makes it link. So do I have to have one for 32-bits and one for 64-bits? Do I need something like:

!DEC$ IF DEFINED (X64) (is there a way to conditionally test for 64-bit?)
!dec$ attributes alias:'_clearfp' :: clearfp
!DEC$ ELSE
!dec$ attributes alias:'__clearfp' :: clearfp
!DEC$ END

I am trying to avoid such code. What is the deal with that little underscore?

Example 2:

Fortran code:

SUBROUTINE PTpropcalcs(OB,CC,P,T,D,I,H,V,S)
!DEC$ ATTRIBUTES C, ALIAS:'_PTpropcalcs' :: PTpropcalcs
!DEC$ ATTRIBUTES VALUE :: OB
!DEC$ ATTRIBUTES VALUE :: CC
!DEC$ ATTRIBUTES REFERENCE :: P
!DEC$ ATTRIBUTES REFERENCE :: T
!DEC$ ATTRIBUTES REFERENCE :: D
!DEC$ ATTRIBUTES REFERENCE :: I
!DEC$ ATTRIBUTES REFERENCE :: H
!DEC$ ATTRIBUTES REFERENCE :: V
!DEC$ ATTRIBUTES REFERENCE :: S
INTEGER OB, CC
DOUBLE PRECISION P, T, D, I, H, V, S
END SUBROUTINE

CALL PTpropcalcs(OBJECT, PTCALLBACK, PRESSURE, TEMPERATURE, DENSITY, INTERNALENERGY, ENTHALPY, VISCOSITY, SOUNDSPEED);

C code:

extern "C"
void PTpropcalcs(int OB,
int CC,
double* P,
double* T,
double* D,
double* I,
double* H,
double* V,
double* S)
{
//C method....

In 32-bit mode it links fine but in 64-bit mode it complains about an unresolved external _PTpropcalcs.
I was able to fix example two by removing the line "!DEC$ ATTRIBUTES C, ALIAS:'_PTpropcalcs' :: PTpropcalcs" from the Fortran code and changing the C method name to PTPROPCALCS. But I do not know if it will now have link issues back in 32-bit mode?

Any thoughts on this? We have lots of code that calls between C and Fortran that links and compiles fine, I am not sure why the above two are problematic.

What is the best way to declare items such as these so they compile and link fine in both 32 and 64-bit world? Usually I have paid little attention to it in the past. Usually you declare it, it links, it works. But we have lots of old code and various different ways and different compilers over the years of doing this.
0 Kudos
5 Replies
Steven_L_Intel1
Employee
617 Views
Use this instead:

[plain]          SUBROUTINE PTpropcalcs(OB,CC,P,T,D,I,H,V,S) BIND(C,NAME="PTpropcalcs")
          INTEGER, VALUE :: OB, CC
          DOUBLE PRECISION P, T, D, I, H, V, S
          END SUBROUTINE[/plain]
0 Kudos
mecej4
Honored Contributor III
617 Views
Compilers deliberately use different name decorations when targeting X86 and X64, for a number of very good reasons. Obviously, it is impossible to use the same register usage conventions in X64 as were used in X86!

Any programs that mix C and Fortran have to use one of the approved ways of doing mixed-language programming:

(i) the older way, using either compiler flags or directives, gives fine control but is compiler specific, if you use directives, the aliases you specify in the Fortran part have to be consistent with what the C compiler generates.

(ii) the new way, which is to use the C interoperability features of Fortran 200X, wherein the Fortran compiler has a specific "companion C processor".
0 Kudos
van_der_merwe__ben
New Contributor II
617 Views
We have lots of other mixed calls which give no problems. It seems mostly to be cases that use 'alias' that are problematic. I guess the solution is to remove the alias or try and not use it whenever possible. Though in the case of the clearfp it seems necessary to use it (though I wouuld generally avoid calling from Fortran directly into the VC runtime DLLs).

Just FYI: The linker does detect whether an OBJ file is 32 or 64-bit. Trying to (accidentally) link a mixture of 32 and 64-bit OBJs gives a very clear error message. All the OBJs must match the 32 or 64-bit target setting passed to the linker. Thank heavens for that detection / error!

Thanks for the thoughts.
0 Kudos
van_der_merwe__ben
New Contributor II
617 Views
By the way, I did stumble across a wikipedia article which states that the Microsoft 32-bit Windows compiler does prepand an underscore. Sadly it says nothing about the 64-bit compiler (though it does specifically say "32-bit"), or whether this is a 32-bit thing only.
0 Kudos
Steven_L_Intel1
Employee
617 Views
The 64-bit convention on Windows is no leading underscore. Using BIND(C) will let the compiler worry about this, but if you want to use ATTRIBUTES ALIAS, remove the underscore from the ALIAS string and add the DECORATE keyword.
0 Kudos
Reply