The naming convention determines how a language alters a symbol name as it places the name in an .OBJ file. This is an issue for external data symbols shared between modules as well as for external routines. Parameter names are never affected. The reasons for altering the name include case sensitivity or lack thereof, type decoration, and other issues. Note that you can always see exactly how a name has been placed in an .OBJ file by using the DUMPBIN utility with the /SYMBOLS option. If naming conventions are not reconciled, the program cannot successfully link. You will receive an “unresolved external” error.
Naming conventions are closely related to calling conventions because the keywords that specify calling conventions affect naming conventions as well. However, C/C++ preserves case sensitivity in its symbol tables and Fortran does not, which can necessitate some additional work on your part. Fortunately, you can use the Fortran ALIAS attribute to resolve any discrepancy in names.
The following table summarizes how C, Fortran, and C++ handle public names.
Naming Conventions in C, Fortran, and C++
Language | Name translated as | Case of name in OBJ file |
C, cdecl (default) | _name | Mixed case preserved |
C, __stdcall | _name@nn | Mixed case preserved |
Fortran [C] | _name | All lowercase |
Fortran [STDCALL] | _name@nn | All lowercase |
Fortran default | _name@nn | All uppercase |
C++ | _name@@decoration | Mixed case preserved |
In the previous table, nn represents the stack space, in decimal notation, occupied by parameters. For example, assume a function is declared in C as
extern int __stdcall Sum_Up( int a, int b, int c );
Each integer occupies 4 bytes, so the symbol name placed in the .OBJ file is:
_Sum_Up@12
Case sensitivity can present a problem. The 32-bit linker always distinguishes case. The strategy you use to handle a discrepancy due to case depends on whether the situation involves:
If you call a Fortran routine from C and cannot recompile the Fortran code, and if the routine uses Fortran defaults, you must use an all-uppercase name to make the call. Use of the __stdcall convention is not enough, because __stdcall (unlike the fortran keyword in 16-bit code) always preserves case. Fortran generates all-uppercase names by default and the C code must match it.
For example, this prototype sets up a call to a Fortran function ffarctan
:
extern float __stdcall FFARCTAN( float angle );
If the name of the routine appears as all lowercase in C, naming conventions are automatically correct when the C or STDCALL attribute is applied to the Fortran declaration. Any case may be used in the Fortran source code, including mixed case; the C and STDCALL attributes change the name to all lowercase. Note that this is a way in which STDCALL differs from the Fortran default behavior.
If the name of the routine appears as mixed-case in C, and you cannot change the name, you can resolve naming conflicts only by using the Fortran ALIAS attribute. ALIAS is required in this situation so that Fortran will generate mixed-case names.
To use the ALIAS attribute, place the name in quotation marks exactly as it is to appear in the .OBJ file. For example, suppose you are calling a C function that has the following prototype:
extern void My_Proc (int i);
The Fortran call to this function should be declared with the following INTERFACE block:
INTERFACE TO SUBROUTINE My_Proc [C, ALIAS:’_My_Proc’] (I)
INTEGER*4 I
END
Note When using the __stdcall convention, both Fortran and C should calculate parameter-space size by rounding each parameter upward to multiples of four (because it is more efficient to keep the stack-pointer aligned on 4-byte boundaries). Thus, the function Print_Nums, which is passed a byte, a short, and a long integer should be translated as _Print_Nums@12. However, there is an early version of 32-bit Fortran that translates this as _Print_Nums@7, not rounding upward. To correct the discrepancy, use the ALIAS attribute.