Mixing PGF90 (Fortran) and PGCC (C++)

Hello,

I am using Fortran and I wish to call C++ functions from Fortran. Here is an example:

File cppfile.cpp:

// #include <iostream>
//using namespace std;
extern "C"
{
int add_(int a, int b)
{
//	cout << a << " + " << b << " = " << a + b << endl;
	return a + b;
} 
}

File fortranfile.f:

      PROGRAM MAIN
      INTEGER a, b, c
      a = 1
      b = 2
      c = add(a,b)

      WRITE(*, *) c

      STOP
      END

This can be compiled as follows:

pgf90 -c fortranfile.f
pgCC -c cppfile.cpp
pgf90 fortranfile.o cppfile.o -o runningprog

So far so good. Now I want to use the “cout” from the c++ library so I uncomment the 3 commented lines in cppfile.cpp:

#include <iostream>
using namespace std;
extern "C"
{
int add_(int a, int b)
{
	cout << a << " + " << b << " = " << a + b << endl;
	return a + b;
} 
}

If I compile in the same way I obtain the errors:

main.o: In function `__sti___8_main_cpp_e760b389':
main.cpp:(.text+0x1e): undefined reference to `std::ios_base::_Loc_init::__ct( (void))'
main.cpp:(.text+0x2a): undefined reference to `__record_needed_destruction'
main.cpp:(.text+0x36): undefined reference to `std::ios_base::Init::__ct( (void))'
main.cpp:(.text+0x42): undefined reference to `__record_needed_destruction'
main.o: In function `.st885':
main.cpp:(.data+0x10): undefined reference to `std::ios_base::Init::__dt( (void))'
main.o: In function `.st884':
main.cpp:(.data+0x20): undefined reference to `std::ios_base::_Loc_init::__dt( (void))'

Obviously the C++ stuff is unknown during the linking process. How do I link correctly? What is the PG Library to link to the program such that it works fine?

Thank you for any suggestions,

Cheers, christian

Hi Christian,

Great question! As of the PGI 7.2-4 release, we added the flag “-pgcpplibs” which will add all the required C++ libraries. For earlier versions, add “-lstd -lC” to the link.

Example:

grandcanyon:/tmp% pgf90 -c test.f
grandcanyon:/tmp% pgcpp -c add.cpp
grandcanyon:/tmp% pgf90 test.o add.o -pgcpplibs
grandcanyon:/tmp% pgf90 test.o add.o -lstd -lC
grandcanyon:/tmp% a.out
-736083452 + -736083448 = -1472166900
            0
FORTRAN STOP

Now that we’ve gotten it link, notice the odd numbers? Fortran passes values by reference so you need to update your add function to integer pointers.

Example:

grandcanyon:/tmp% cat add.cpp
#include <iostream>
using namespace std;
extern "C"
{
int add_(int* a, int* b)
{
   cout << *a << " + " << *b << " = " << *a + *b << endl;
   return *a + *b;
}
}
grandcanyon:/tmp% pgf90 -c test.f
grandcanyon:/tmp% pgcpp -c add.cpp
grandcanyon:/tmp% pgf90 test.o add.o -lstd -lC -o a.out
grandcanyon:/tmp% a.out
1 + 2 = 3
            0
FORTRAN STOP

We’re not quite done yet since the fortran “C” variable is printing out “0” instead of “3”. The problem here is that “add” has a default kind of REAL. To fix, explicitly declare “add” as an INTEGER.

Example:

 grandcanyon:/tmp% cat test.f
      PROGRAM MAIN
      INTEGER a, b, c
      INTEGER add
      a = 1
      b = 2
      c = add(a,b)

      WRITE(*, *) c

      STOP
      END
grandcanyon:/tmp% pgf90 -c test.f
grandcanyon:/tmp% pgf90 test.o add.o -lstd -lC -o a.out
grandcanyon:/tmp% a.out
1 + 2 = 3
            3
FORTRAN STOP

Note that Chapter 10 of the PGI User’s Guide (http://www.pgroup.com/doc/pgiug.pdf) gives more detailed information about inter-language calling.

Hope this helps,
Mat

Dear Mkcolg,

thank you for your detailled response. Linking with -lC and -lstd works fine (it is PGI version 7.0-2). Just a concern about the documentation, the PGI Users guide: I tried to find which C/C++ are neccessary when linking with the Fortran compiler but I didn’t find any hints. Did I miss something or is it just not written in the manual?

Is it true that when linking with the pgCC command the neccessary C/C++ libs are automatically linked to the final executable?

Cheers, christian

Hi Christian,

Just a concern about the documentation, the PGI Users guide: I tried to find which C/C++ are neccessary when linking with the Fortran compiler but I didn’t find any hints. Did I miss something or is it just not written in the manual?

Thanks for pointing this out. I’ve asked our technical writers to add the libraries to the example of Fortran calling C++ in the PGI User’s guide.

Is it true that when linking with the pgCC command the neccessary C/C++ libs are automatically linked to the final executable?

Yes, however the F90 runtime libraries would not be added, so you would need to add the flag “-pgf90libs” or the F90 libraries directly “-lpgf90 -lpgf90_rpm1 -lpgf902 -lpgf90rtl -lpgftnrtl”. Also since in your example the “main” program is in the Fortran source, you would also need to add the “f90main.o” file found in your install’s “lib” directory.

Example:

grandcanyon:/tmp% pgcpp test.o add.o -o a.out -pgf90libs /usr/pgi/linux86-64/7.0-7/lib/f90main.o
grandcanyon:/tmp% a.out
1 + 2 = 3
            3
FORTRAN STOP
  • Mat

Hello Mat,

thanks for this hint. I already thought about the issue with the main function. That you, too, for pointing out the libs that are neccessary if I linked with an invocation of the C-compiler.

Regards,

Christian