Skip to content. Skip to navigation

ICTP Portal

Sections
You are here: Home Manuals on-line PGI Compiler pgiws_ug PGI Workstation User's Guide - 6 Inter-language Calling
Personal tools
Document Actions

PGI Workstation User's Guide - 6 Inter-language Calling

<< << " border=0> >> > " border=0> Title Contents Index Home Help

6 Inter-language Calling


This chapter describes inter-language calling conventions for C, C++, and Fortran programs using the PGI compilers. The following sections describe how to call a Fortran function or subroutine from a C or C++ program and how to call a C or C++ function from a Fortran program. For information on calling assembly language programs, refer to Appendix A, Run-time Environment.

6.1 Overview of Calling Conventions

This chapter includes information on the following topics:

  • Functions and subroutines in Fortran, C, and C++
  • Naming and case conversion conventions
  • Compatible data types
  • Argument passing and special return values
  • Arrays and Indexes
  • Win32 calling conventions

Default Fortran calling conventions under Win32 differ from those used under UNIX operating systems. Win32 programs compiled using the -Munix Fortran command-line option use the UNIX convention rather than the default Win32 convention. Sections 6.1 through 6.13 describe how to perform inter-language calling using the UNIX convention. All information in those sections pertaining to compatibility of arguments applies to Win32 as well, but see section 6.14, Win32 Calling Conventions, for details on the symbol name and argument passing conventions used on Win32.

6.2 Inter-language Calling Considerations

In general, when argument data types and function return values agree you can call a C or C++ function from Fortran and likewise, you can call a Fortran function from C or C++. Where data types for arguments do not agree, for example the Fortran COMPLEX type does not have a matching type in C, it is still possible to provide inter-language calls but there are no general calling conventions for such cases (you may need to develop special procedures to handle such cases).

Note that if a C++ function contains objects with constructors and destructors, calling such a function from either C or Fortran will not be possible unless the initialization in the main program is performed from a C++ program where constructors and destructors are properly initialized.

In general, you can call a C function from C++ without problems as long as you use the extern "C" keyword to declare the C function in the C++ program. This prevents name mangling for the C function name. If you want to call a C++ function from C, likewise you have to use the extern "C" keyword to declare the C++ function. This keeps the C++ compiler from mangling the name of the function.

You can use the __cplusplus macro to allow a program or header file to work for both C and C++. For example, the following defines in the header file stdio.h allow this file to work for both C and C++.

#ifndef _STDIO_H
#define _STDIO_H

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
.
. /* Functions and data types defined... */
.
#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif

C++ member functions cannot be declared extern, as their names will always be mangled. Therefore, C++ member functions cannot be called from C or Fortran.

6.3 Functions and Subroutines

Fortran, C, and C++ define functions and subroutines differently. For a Fortran program calling a C or C++ function, observe the following return value convention:

  • When the C or C++ function returns a value, call it from Fortran as a function, otherwise call it as a subroutine.

For a C/C++ program calling a Fortran function, the call should return a similar type. Table 6-1 lists compatible types. If the call is to a Fortran subroutine or a Fortran CHARACTER function, call it from C/C++ as a function that returns void. The exception to this convention is when a Fortran subroutine has alternate returns; call such a subroutine from C/C++ as a function returning int whose value is the value of the integer expression specified in the alternate RETURN statement.

6.4 Upper and Lower Case Conventions, Underscores

By default, on UNIX systems all Fortran symbol names are converted to lower-case. C and C++ are case sensitive, so upper-case function names stay upper-case. When you use inter-language calling you can either name your C/C++ functions with lower-case names, or invoke the Fortran compiler command with the option -Mupcase, in which case it will not convert symbol names to lower-case.

When programs are compiled using one of the PGI Fortran compilers on UNIX systems, an underscore is appended to Fortran global names (names of functions, subroutines and common blocks). This mechanism distinguishes Fortran name space from C/C++ name space. If you call a C/C++ function from Fortran, you should rename the C/C++ function by appending an underscore (or use C$PRAGMA C in the Fortran program, refer to Chapter 9, Optimization Directives and Pragmas, for details on C$PRAGMA C) If you call a Fortran function from C/C++, you should append an underscore to the Fortran function name in the calling program.

6.5 Compatible Data Types

Table 6-1 shows compatible data types between Fortran and C/C++. Table 6-2 shows how the Fortran COMPLEX type may be represented in C/C++. If you can make your function/subroutine parameters and return values match types, you should be able to use inter-language calling. An exception is that you cannot directly call a COMPLEX function from C/C++. Refer to Section 6.6.3, Complex Return Values, for details on how to call a COMPLEX function indirectly.

Table 6-1 Fortran and C/C++ Data Type Compatibility

Fortran
Type (lower case)

C/C++
Type

Size
(bytes)

character x


char x


1


character*n x


char x[n]


n


real x


float x


4


real*4 x


float x


4


real*8 x


double x


8


double precision


double x


8


integer x


int x


4


integer*1 x


signed char x


1


integer*2 x


short x


2


integer*4 x


int x


4


integer*8 x


long long x


8


logical x


int x


4


logical*1 x


char x


1


logical*2 x


short x


2


logical*4


int x


4


logical*8


long long x


8


Table 6-2 Fortran and C/C++ Representation of the COMPLEX Type

Fortran
Type (lower case)

C/C++
Type

Size
(bytes)

complex x


struct
{float r,i;} x;


8


complex*8 x


struct
{float r,i;} x;


8


double complex x


struct
{double dr,di;} x;


16


6.5.1 Fortran Named Common Blocks

A named Fortran common block can be represented in C/C++ by a structure whose members correspond to the members of the common block. The name of the structure in C/C++ must have the added underscore. For example the Fortran common block:

INTEGER I
COMPLEX C
DOUBLE COMPLEX CD
DOUBLE PRECISION D
COMMON /COM/ i, c, cd, d

is represented in C with the following equivalent:

extern struct {
int i;
struct {float real, imag;} c;
struct {double real, imag;} cd;
double d;
} com_;

and in C++ with the following equivalent:

extern "C" struct {
int i;
struct {float real, imag;} c;
struct {double real, imag;} cd;
double d;
} com_;

6.6 Argument Passing and Return Values

In Fortran, arguments are passed by reference (i.e. the address of the argument is passed, rather than the argument itself). In C/C++, arguments are passed by value, except for strings and arrays, which are passed by reference. Due to the flexibility provided in C/C++, you can work around these differences. Generally solving the parameter passing differences involves intelligent use of the & and * operators in argument passing when C/C++ calls Fortran and in argument declarations when Fortran calls C/C++.

For strings declared in Fortran as type CHARACTER, an argument representing the length of the string is passed to a calling function. On UNIX systems, or when using the UNIX calling convention on Win32 (-Munix), the compiler places the length argument(s) at the end of the parameter list, following the other formal arguments. The length argument is passed by value, not by reference.

6.6.1 Passing By Value (%VAL)

When passing parameters from a Fortran subprogram to a C/C++ function it is possible to pass by value using the %VAL function. If you enclose a Fortran parameter with %VAL(), the parameter is passed by value. For example, the following call passes the integer I and the logical BVAR by value.

INTEGER*1	I
LOGICAL*1 BVAR

CALL CVALUE (%VAL(I), %VAL(BVAR))

6.6.2 Character Return Values

Section 6.3, Functions and Subroutines, describes the general rules for return values for C/C++ and Fortran inter-language calling. There is a special return value to consider. When a Fortran function returns a character, two arguments need to be added at the beginning of the C/C++ calling function's argument list: the address of the return character or characters, and the length of the return character. Example 6-1 illustrates the extra parameters, tmp and 10, supplied by the caller:

    CHARACTER*(*) FUNCTION CHF( C1, I)
CHARACTER*(*) C1
INTEGER I
END extern void chf_();
char tmp[10];
char c1[9];
int i;
chf_(tmp, 10, c1, &i, 9);

Example 6-1 Character Return Parameters

If the Fortran function is declared to return a character value of constant length, for example CHARACTER*4 FUNCTION CHF(), the second extra parameter representing the length must still be supplied, but is not used.



Note

The value of the character function is not automatically NULL-terminated.

6.6.3 Complex Return Values

Fortran complex functions return their values in multiple floating point registers; consequently, you cannot directly call a Fortran complex function from C/C++. It is possible for a C/C++ function to pass a pointer to a memory area to a function, which calls the COMPLEX function and stores the value returned by the complex function. Example 6-2 illustrates COMPLEX return values.

extern void inter_cf_();
typedef struct {float real, imag;} cplx;
cplx c1;
int i;
inter_cf_(&c1, &i);

SUBROUTINE INTER_CF(C, I)
COMPLEX C
COMPLEX CF
C = CF(I)
RETURN
END COMPLEX FUNCTION CF(I)
. . .
END


Example 6-2 COMPLEX Return Values

6.7 Array Indices

C/C++ arrays and Fortran arrays use different default initial array index values. By default, C/C++ arrays start at 0 and Fortran arrays start at 1. If you adjust your array comparisons so that a Fortran second element is compared to a C/C++ first element, and adjust similarly for other elements, you should not have problems working with this difference. If this is not satisfactory, you can declare your Fortran arrays to start at zero.

Another difference between Fortran and C/C++ arrays is the storage method used. Fortran uses column-major order and C/C++ use row-major order. For one-dimensional arrays, as you might expect, this poses no problems. For two dimensional arrays, where there are an equal number of rows and columns, row and column indexes can simply be reversed. For arrays other than single dimensional arrays, and square two-dimensional arrays, inter-language function mixing is not recommended.

6.8 Example - Fortran Calling C

Example 6-4 shows a C function that is called by the Fortran main program shown in Example
6-3. Notice that each argument is defined as a pointer, since Fortran passes by reference. Also notice that the C function name uses all lower-case and a trailing "_".

  	    logical*1              bool1
character letter1
integer*4 numint1, numint2
real numfloat1
double precision numdoub1
integer*2 numshor1
external cfunc
call cfunc (bool1, letter1, numint1, numint2,
& numfloat1, numdoub1, numshor1)
write( *, "(L2, A2, I5, I5, F6.1, F6.1, I5)")
& bool1, letter1, numint1, numint2, numfloat1,
& numdoub1, numshor1
end

Example 6-3 Fortran Main Program fmain.f

#define TRUE 0xff
#define FALSE 0
void
cfunc_( bool1, letter1, numint1, numint2, numfloat1,\
numdoub1, numshor1, len_letter1)
char *bool1, *letter1;
int *numint1, *numint2;
float *numfloat1;
double *numdoub1;
short *numshor1;
int len_letter1;
{
*bool1 = TRUE;
*letter1 = 'v';
*numint1 = 11;
*numint2 = -44;
*numfloat1 = 39.6 ;
*numdoub1 = 39.2 ;
*numshor1 = 981;
}

Example 6-4 C function cfunc_

Compile and execute the program fmain.f with the call to cfunc_ using the following command lines:

$ pgcc -c cfunc.c
$ pgf90 cfunc.o fmain.f

Executing the a.out file should produce the following output:

T  v  11  -44 39.6  39.2  981

6.9 Example - C Calling Fortran

Example 6-6 shows a C main program that calls the Fortran subroutine shown in Example 6-5. Notice that each call uses the & operator to pass by reference. Also notice that the call to the Fortran subroutine uses all lower-case and a trailing "_".

       subroutine forts ( bool1, letter1, numint1, 
& numint2, numfloat1, numdoub1, numshor1)
logical*1 bool1
character letter1
integer numint1, numint2
double precision numdoub1
real numfloat1
integer*2 numshor1

bool1 = .true.
letter1 = "v"
numint1 = 11
numint2 = -44
numdoub1 = 902
numfloat1 = 39.6
numshor1 = 299
return
end

Example 6-5 Fortran Subroutine forts.f

main ()
{
char bool1, letter1;
int numint1, numint2;
float numfloat1;
double numdoub1;
short numshor1;
extern void forts_ ();
forts_(&bool1,&letter1,&numint1,&numint2,&numfloat1,
&numdoub1,&numshor1, 1);
printf(" %s %c %d %d %3.1f %.0f %d\n",
bool1?"TRUE":"FALSE",letter1,numint1,
numint2, numfloat1, numdoub1, numshor1);
}

Example 6-6 C Main Program cmain.c

To compile this Fortran subroutine and C program, use the following commands:

$ pgcc -c cmain.f
$ pgf90 -Mnomain cmain.o forts.f

Executing the resulting a.out file should produce the following output:

TRUE  v  11 -44  39.6  902  299

6.10 Example - C ++ Calling C

void cfunc(num1, num2, res)
int num1, num2, *res;
{
printf("func: a = %d b = %d ptr c = %x\n",num1,num2,res);
*res=num1/num2;
printf("func: res = %d\n",*res);
}

Example 6-7 Simple C Function cfunc.c


extern "C" void cfunc(int n, int m, int *p);
#include <iostream>
main()
{
int a,b,c;
a=8;
b=2;
cout << "main: a = "<<a<<" b = "<<b<<" ptr c = "<<&c<< endl;
cfunc(a,b,&c);
cout << "main: res = "<<c<<endl;
}

Example 6-8 C++ Main Program cpmain.C Calling a C Function

To compile this C function and C++ main program, use the following commands:

$ pgcc -c csub.c
$ pgCC cpmain.C csub.o

Executing the resulting a.out file should produce the following output:

main: a = 8 b = 2 ptr c = 0xbffffb94
func: a = 8 b = 2 ptr c = bffffb94
func: res = 4
main: res = 4

6.11 Example - C Calling C++

#include <iostream>
extern "C" void cpfunc(int num1,int num2,int *res)
{
cout << "func: a = "<<num1<<" b = "<<num2<<" ptr c ="<<res<<endl;
*res=num1/num2;
cout << "func: res = "<<res<<endl; }

Example 6-9 Simple C++ Function cpfunc.C with Extern C

extern void cpfunc(int a, int b, int *c);
#include <stdio.h>
main()
{
int a,b,c;
a=8;
b=2;
printf("main: a = %d b = %d ptr c = %x\n",a,b,&c);
cpfunc(a,b,&c);
printf("main: res = %d\n",c);
}

Example 6-10 C Main Program cmain.c Calling a C++ Function

To compile this C function and C++ main program, use the following commands:

$ pgcc -c cmain.c
$ pgCC cmain.o cpsub.C

Executing the resulting a.out file should produce the following output:

main: a = 8 b = 2 ptr c = 0xbffffb94
func: a = 8 b = 2 ptr c = bffffb94
func: res = 4
main: res = 4

Note that you cannot use the extern "C" form of declaration for an object's member functions.

6.12 Example - Fortran Calling C++

The Fortran main program shown in Example 6-11 calls the C++ function shown in Example
6-12. Notice that each argument is defined as a pointer in the C++ function, since Fortran passes by reference. Also notice that the C++ function name uses all lower-case and a trailing "_":

     logical*1              bool1
character letter1
integer*4 numint1, numint2
real numfloat1
double precision numdoub1
integer*2 numshor1
external cfunc
call cpfunc (bool1, letter1, numint1,
& numint2, numfloat1, numdoub1, numshor1)
write( *, "(L2, A2, I5, I5, F6.1, F6.1, I5)")
& bool1, letter1, numint1, numint2, numfloat1,
& numdoub1, numshor1
end

Example 6-11 Fortran Main Program fmain.f calling a C++ function

#define TRUE 0xff
#define FALSE 0
extern "C" {
extern void cpfunc_ (
char *bool1, *letter1,
int *numint1, *numint2,
float *numfloat1,
double *numdoub1,
short *numshort1,
int len_letter1) {
*bool1 = TRUE;
*letter1 = 'v';
*numint1 = 11;
*numint2 = -44;
*numfloat1 = 39.6;
*numdoub1 = 39.2;
*numshort1 = 981;
}
}

Example 6-12 C++ function cpfunc.C

Assuming the Fortran program is in a file fmain.f, and the C++ function is in a file cpfunc.C, create an executable, using the following command lines:

$ pgCC -c cpfunc.C
$ pgf90 cpfunc.o fmain.f

Executing the a.out file should produce the following output:

T  v  11  -44 39.6  39.2  981

6.13 Example - C++ Calling Fortran

Example 6-13 shows a Fortran subroutine called by the C++ main program shown in Example
6-14. Notice that each call uses the & operator to pass by reference. Also notice that the call to the Fortran subroutine uses all lower-case and a trailing "_":

      subroutine forts ( bool1, letter1, numint1, 
& numint2, numfloat1, numdoub1, numshor1)
logical*1 bool1
character letter1
integer numint1, numint2
double precision numdoub1
real numfloat1
integer*2 numshor1
bool1 = .true. ; letter1 = "v" ; numint1 = 11 ; numint2 = -44
numdoub1 = 902 ; numfloat1 = 39.6 ; numshor1 = 299
return
end

Example 6-13 Fortran Subroutine forts.f

#include <iostream>
extern "C" { extern void forts_(char *,char *,int *,int *,
float *,double *,short *); }
main ()
{
char bool1, letter1;
int numint1, numint2;
float numfloat1;
double numdoub1;
short numshor1;
forts_(&bool1,&letter1,&numint1,&numint2,&numfloat1,
&numdoub1,&numshor1);
cout << " bool1 = ";
bool1?cout << "TRUE ":cout << "FALSE "; cout << endl;
cout << " letter1 = " << letter1 << endl;
cout << " numint1 = " << numint1 << endl;
cout << " numint2 = " << numint2 << endl;
cout << " numfloat1 = " << numfloat1 << endl;
cout << " numdoub1 = " << numdoub1 << endl;
cout << " numshor1 = " << numshor1 << endl;
}

Example 6-14 C++ main program cpmain.C

To compile this Fortran subroutine and C++ program, use the following command lines:

$ pgf90 -c forts.f
$ pgCC forts.o cpmain.C -lpgf90 -lpgf90_rpm1 -lpgf902 \
-lpgf90rtl -lpgftnrtl

Executing this C++ main should produce the following output:

bool1     = TRUE
letter1 = v
numint1 = 11
numint2 = -44
numfloat1 = 39.6
numdoub1 = 902
numshor1 = 299

Note that you must explicitly link in the PGF90 runtime support libraries when linking pgf90-compiled program units into C or C++ main programs. When linking pgf77-compiled program units into C or C++ main programs, you need only link in -lpgftnrtl.

6.14 Win32 Calling Conventions

Aside from name-mangling considerations in C++, the calling convention (i.e. the symbol name to which the subroutine or function name is mapped and the means by which arguments are passed) for C/C++ is identical between most compilers on Win32 and UNIX variants. However, Fortran calling conventions vary widely between Win32 and UNIX (and between UNIX implementations, for that matter).

6.14.1 Win32 Fortran Calling Conventions

Four styles of calling conventions are supported using the PGI Fortran compilers for Win32: Default, C, STDCALL, and UNIX. Default is the method used in the absence of compilation flags or directives to alter the default. The C or STDCALL conventions are used if an appropriate compiler directive is placed in a program unit containing the call. The C and STDCALL conventions are typically used to call routines coded in C or assembly language which depend on these conventions. The UNIX convention is used in any Fortran program unit compiled using the -Munix compilation flag. Table 6-3 outlines each of these calling conventions.

Table 6-3 Calling Conventions Supported by the PGI Fortran Compilers

Convention

Default

STDCALL

C

UNIX

Case of symbol name


Upper


Lower


Lower


Lower


Leading underscore


Yes


Yes


Yes


Yes


Trailing underscore


No


No


No


Yes


Argument byte count added


Yes


Yes


No


No


Arguments passed by reference


Yes


No*


No*


Yes


Character argument byte counts passed


After each char argument


No


No


End of argument list


Character strings truncated to first character and passed by value


No


Yes


Yes


No


varargs support


No


No


Yes


No


Caller cleans stack


No


No


Yes


Yes


* Except arrays, which are always passed by reference even in the STDCALL and C conventions

NOTE: While it is compatible with the Fortran implementations of Microsoft and several other vendors, the C calling convention supported by the PGI Fortran compilers for Win32 is not strictly compatible with the C calling convention used by most C/C++ compilers. In particular, symbol names produced by PGI Fortran compilers using the C convention are all lower case. The standard C convention is to preserve mixed-case symbol names. You can cause any of the PGI Fortran compilers to preserve mixed-case symbol names using the -Mupcase option, but be aware that this could have other ramifications on your program.

6.14.2 Symbol Name Construction and Calling Example

This section presents an example of the rules outlined in table 6-3. In the pseudocode used below, %addr refers to the address of a data item while %val refers to the value of that data item. Subroutine and function names are converted into symbol names according to the rules outlined in table 6-3. Consider the following subroutine call:

call work ( `ERR', a, b, n)

where a is a double precision scalar, b is a real vector of size n, and n is an integer.

Default - The symbol name for the subroutine is constructed by pre-pending an underscore, converting to all upper case, and appending an @ sign followed by an integer indicating the total number of bytes occupied by the argument list. Byte counts for character arguments appear immediately following the corresponding argument in the argument list. Thus the pseudo-code for the above call using Default conventions looks as follows:

call _WORK@20 ( %addr(`ERR'), 3, %addr(a), %addr(b), %addr(n))

STDCALL - The symbol name for the subroutine is constructed by pre-pending an underscore, converting to all lower case, and appending an @ sign followed by an integer indicating the total number of bytes occupied by the argument list. Character strings are truncated to the first character in the string, which is passed by value as the first byte in a 4-byte word. Thus the pseudo-code for the above call using STDCALL conventions looks as follows:

call _work@20 ( %val(`E'), %val(a), %addr(b), %val(n))

Note that in this case there are still 20 bytes in the argument list. However, rather than 5 4-byte quantities as in the Default convention, there are 3 4-byte quantities and 1 8-byte quantity (the double precision value of a).

C - The symbol name for the subroutine is constructed by pre-pending an underscore and converting to all lower case. Character strings are truncated to the first character in the string, which is passed by value as the first byte in a 4-byte word. Thus the pseudo-code for the above call using C conventions looks as follows:

call _work ( %val(`E'), %val (a), %addr(b), %val(n))

UNIX - The symbol name for the subroutine is constructed by pre-pending an underscore, converting to all lower case, and appending an underscore. Byte counts for character strings appear in sequence following the last argument in the argument list. Thus the pseudo-code for the above call using UNIX conventions looks as follows:

call _work_ ( %addr(`ERR'), %addr (a), %addr(b), %addr(n), 3)

6.14.3 Using the Default Calling Convention

Using the Default calling convention is straightforward. This convention will be used if no directives are inserted to modify calling conventions and if the -Munix compilation flag is not used. See above for a complete description of the Default convention.

6.14.4 Using the STDCALL Calling Convention

Using the STDCALL calling convention requires the insertion of a compiler directive into the declarations section of any Fortran program unit which calls the STDCALL program unit. This directive has no effect when the -Munix compilation flag is used, meaning you cannot mix UNIX-style argument passing and STDCALL calling conventions within the same file. Syntax for the directive is as follows:

!MS$ATTRIBUTES STDCALL ::  work

Where work is the name of the subroutine to be called using STDCALL conventions. More than one subroutine may be listed, separated by commas. See above for a complete description of the implementation of STDCALL.

NOTE: The directive prefix !DEC$ is also supported, but requires a space between the prefix and the directive keyword ATTRIBUTES. The ! must begin the prefix when compiling using Fortran 90 freeform format. The characters C or * can be used in place of ! in either form of the prefix when compiling used fixed-form (F77-style) format. The directives are completely case insensitive.

6.14.5 Using the C Calling Convention

Using the C calling convention requires the insertion of a compiler directive into the declarations section of any Fortran program unit which calls the C program unit. This directive has no effect when the -Munix compilation flag is used, meaning you cannot mix UNIX-style argument passing and C calling conventions within the same file. Syntax for the directive is as follows:

!MS$ATTRIBUTES C ::  work

Where work is the name of the subroutine to be called using C conventions. More than one subroutine may be listed, separated by commas. See above for a complete description of the implementation of the C calling convention.

NOTE: The directive prefix !DEC$ is also supported, but requires a space between the prefix and the directive keyword ATTRIBUTES. The ! must begin the prefix when compiling using Fortran 90 freeform format. The characters C or * can be used in place of ! in either form of the prefix when compiling used fixed-form (F77-style) format. The directives are completely case insensitive.

6.14.6 Using the UNIX Calling Convention

Using the UNIX calling convention is straightforward. Any program unit compiled using -Munix compilation flag will use the UNIX convention.


<< << " border=0> >> > " border=0> Title Contents Index Home Help
Weather
No information available
 

Powered by Plone This site conforms to the following standards: