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
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