c++ main with pgf77 subroutines (argc / argv in Fortran)

I have a code that generates a c++ main (using g++ v4.8.2) and some pgf77 compiled subroutines. From the Fortran routines I’d like to be able to access argc, argv. I’ve tried using GETARG, however it returns empty. If use GETARG within a Fortran MAIN PROGRAM all is well. Some search seems to indicate that sometimes it’s necessary to ‘export’ argc / argv manually with the use of

f_setarg
_gfortran_set_args

or something equivalent. After several attempts I didn’t have an success in managing to get these values passed properly to the Fortran side. I tried going through in the gdb debugger, the calls to GETARG are made along with

__pgio_get_argc

Anyone know of the proper way to deal with this / instrument my c++ main to make sure things work as expected?

A solution to this seems to be making the following calls before calling any fortran subroutines (they need to be declared as extern “C”:

__pgio_set_argc(narg);
__pgio_set_argv(argv);
__pgio_environ();

This then propagates argc and argc properly to the Fortran subroutines. If anyone has a more elegant solution I’m all ears.

If you have a C/C++ main and a fortran subroutine, and you wish the
fortran subroutine to process the command line arguments, then you need to
save the arguments in the main to __argc_save and __argv_save.

Here is an example modified from FAQ | PGI
if you look at inter-language questions.

% more cmain_c.C
#include
int __argc_save;
char **__argv_save;

extern “C” {
extern void forts_( char *, char *, int *,int *,float *, double *,short * );
}



int main(int argc, char **argv)
{
char bool1;
char letter1;
int numint1, numint2;
float numfloat1;
double numdoub1;
short numshor1;
int i;



__argc_save = argc;
__argv_save = argv;

forts_(&bool1,&letter1,&numint1,&numint2,&numfloat1,
&numdoub1,&numshor1);

std::cout << "main: bool1= " << (bool1?“TRUE”:“FALSE”) << std::endl;
std::cout << "main: letter1= " << letter1 << std::endl;
std::cout << "main: numint1= " << numint1 << std::endl;
std::cout << "main: numint2= " << numint2 << std::endl;
std::cout << "main: numfloat1= " << numfloat1 << std::endl;
std::cout << "main: numdoub1= " << numdoub1 << std::endl;
std::cout <<"main: numshor1= " << numshor1 << std::endl;
}


% more forts_c.f90
subroutine forts ( bool1, letter1, numint1, numint2, numfloat1,&
numdoub1, numshor1 )


use, intrinsic :: iso_c_binding, only:C_CHAR,C_BOOL, &
C_INT,C_FLOAT,C_DOUBLE,C_SHORT
logical(C_BOOL) :: bool1
character(C_CHAR) :: letter1
integer(C_INT) :: numint1, numint2
real(C_DOUBLE) :: numdoub1
real(C_FLOAT) :: numfloat1
integer(C_SHORT) :: numshor1
integer numarg, iargc, readarg_num
character(len=256) arg, readarg_string

numarg=iargc()
write(6,)“command line tokens=”, numarg
call getarg(0,arg)
write(6,
)“program name=”,arg
if (numarg .ge. 1) then
do i=1,numarg
call getarg(i,arg)
write(6,*)“token”,i,“=”,arg
end do
end if

bool1 = .true.
letter1=“v”
numint1=123
numint2=-456
numdoub1=5432.1
numfloat1=6789.0
numshor1=53
return
end


The programs above with pgf90 and g++ or pgc++
% pgf90 -c forts_c.f90
% pgc++ -o CtoF_pgi forts_c.o cmain_c.C -pgf90libs
% CtoF_pgi is a program
command line tokens= 3
program name=
CtoF_pgi token 1 =
is
token 2 =
a token 3 =
program
main: bool1= TRUE
main: letter1= v
main: numint1= 123
main: numint2= -456
main: numfloat1= 6789
main: numdoub1= 5432.1
main: numshor1= 53

% g++ -o CtoF cmain_c.C forts_c.o -L$PGI/linux86-64/17.4/lib -lpgf90rtl -lpgf90 -lpgf90_rpm1 -lpgf902 -lpgf90rtl -lpgftnrtl -lpgmp -lpthread -lnspgc -lpgc -lrt -lpthread -lm -lgcc -lc -lgcc -lgcc_s -lnuma
% CtoF is a gcc program
command line tokens= 4
program name=
CtoF
token 1 =
is
token 2 =
a
token 3 =
gcc
token 4 =
program
main: bool1= TRUE
main: letter1= v
main: numint1= 123
main: numint2= -456
main: numfloat1= 6789
main: numdoub1= 5432.1
main: numshor1= 53

Hope this helps.

dave