Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29234 Discussions

How to link ifort and g++ compiled .o files

pilot117
Beginner
2,074 Views
Hi, all

I am new to mac os and ifort. Here i have a basic question: how to link the g++ compiled .o files with ifort compiled .o files?

Below is my very simple example:
an aver.cpp file:
------------------------------------------------------------------
#include
#include
#include
#include

double myaver(double x, double y, double z){

double aver;
aver=(x+y+z)/3;
return aver;
}
--------------------------------------------------------------------
a fortran main.F90 file using myaver function:
-------------------------------------------------------------------
PROGRAM MAIN
REAL x, y,z, average
x=100
y=200
z=300
PRINT *, 'three numbers: ', x, y, z
average = myaver(x,y,z)
PRINT *, 'Average of the three numbers is: ', average
END PROGRAM MAIN
---------------------------------------------------------------------------
now i compile each of them without link (make sure they are 32 bit):
---------------------------------------------------------------------
g++ -c aver.cpp
ifort -m32 -c main.f90
-------------------------------------------------------------------------
then link them
-----------------------------------------------------------------------
ifort -m32 -fPIC -o mytest main.o aver.o
------------------------------------------------------------------------
but i got error :
------------------------------------------------------------------------
Undefined symbols:
"_myaver_", referenced from:
_MAIN__ in main.o
ld: symbol(s) not found
-------------------------------------------------------------------------

how do I resolve this error? I guess I have fundamental misunderstanding here. Hope experts could help me.

many thanks


0 Kudos
8 Replies
TimP
Honored Contributor III
2,074 Views
As you see, the default Fortran name mangling appends an underscore to the function name, while C++ mangling is entirely different. Perhaps not so obvious, the Fortran arguments pass by reference. Consider using the iso_c_interop on the Fortran side, with extern "C" definition on the C++ side.
0 Kudos
pilot117
Beginner
2,074 Views
Quoting - tim18
As you see, the default Fortran name mangling appends an underscore to the function name, while C++ mangling is entirely different. Perhaps not so obvious, the Fortran arguments pass by reference. Consider using the iso_c_interop on the Fortran side, with extern "C" definition on the C++ side.

many thanks, tim18, now i get everything works. But I have some further questions:

the way I did is : the aver.cpp
--------------------------------------------------------------------------------
#include
#include
#include
#include

extern "C" {
void myaver_(float *x, float *y, float *z, float *aver);}

void myaver_(float *x, float *y, float *z,float *aver){

*aver=(*x+*y+*z)/3;
}
------------------------------------------------------------------------------------
and the main.f90 file is

PROGRAM MAIN
REAL x, y,z, average
x=100
y=200
z=300
PRINT *, 'three numbers: ', x, y, z
call myaver(x,y,z, average)
PRINT *, 'Average of the five numbers is: ', average
END PROGRAM MAIN

-------------------------------------------------------------------------------------

then i compile on the MAC OS :
g++ -c aver.cpp
ifort -m32 -c main.f90
ifort -m32 -o mytest aver.o main.o

then i get the correct answer. while I also did the same thing on my RHEL5.3

g++ -c aver.cpp
ifort -c main.f90
ifort -o mytest aver.o main.o -lstdc++

then it works. But a further exploration confused me:
-------------------------------------------------------------------------------------------------
on the RHEL 5.3 | on the MAC OS
nm aver.o | nm aver.o
U __gxx_personality_v0 | 00000000 T _myaver_
0000000000000000 T myaver_ | 00000000 A _myaver_.eh
--------------------------------------------------------------------------------------------------

the __gxx_personality_v0 is the reason to add libstdc++.
I use the same compiler and no other flags. The only difference is RHEL is 64 bit but Mac is 32 bit. Why are the names on the mac os all added "_" in the front? How do I modified the compiler option to make the mac os have the same function names as the RHEL 5.3 ? what is .eh? and how does the RHEL5.3 add __gxx_personality_v0 automatically when compiling?

Hope I am clear. Many thanks!


0 Kudos
TimP
Honored Contributor III
2,074 Views
I believe you're correct about different ABI conventions chosen for 32- and 64-bit. Mac g++ includes some differences specified by Apple, while linux g++ is under the control of an FSF steering committee. Any .o file made by linux g++ includes the __gxx_personality reference. If you had used any C++ syntax, you would need -lstdc++ on both linux and Mac, I suppose.
0 Kudos
pilot117
Beginner
2,074 Views
Quoting - tim18
I believe you're correct about different ABI conventions chosen for 32- and 64-bit. Mac g++ includes some differences specified by Apple, while linux g++ is under the control of an FSF steering committee. Any .o file made by linux g++ includes the __gxx_personality reference. If you had used any C++ syntax, you would need -lstdc++ on both linux and Mac, I suppose.

OK, I see.

Is there any options or flags of "ifort" such that no undercores are added on the function names? I check online and find the gfortran has a flag "fno-underscoring", which could let me add no underscore to the functions in my .cpp file but link successfully.

thanks!




0 Kudos
TimP
Honored Contributor III
2,074 Views
Quoting - pilot117

OK, I see.

Is there any options or flags of "ifort" such that no undercores are added on the function names? I check online and find the gfortran has a flag "fno-underscoring", which could let me add no underscore to the functions in my .cpp file but link successfully.

thanks!




There's no flag to modify leading underscores. You're stuck with using the convention of your OS. You could look up the flags for trailing underscores in ifort documentation, recognizing that changes from default are at your own risk and not an adequate substitute for USE iso_c_interop.
0 Kudos
pilot117
Beginner
2,074 Views
Quoting - tim18
There's no flag to modify leading underscores. You're stuck with using the convention of your OS. You could look up the flags for trailing underscores in ifort documentation, recognizing that changes from default are at your own risk and not an adequate substitute for USE iso_c_interop.

Oh, thanks for pointing out that! I believe you are absolutely right.
0 Kudos
pilot117
Beginner
2,074 Views

I have tried something else using the "decorate". But there is something wrong which i can not figure out:

the main.f90 is written as this:
---------------------------------------------------------------------------------------------------
! File: main.f90
! This program calculates the average of three numbers
PROGRAM MAIN
implicit none

interface
subroutine fc_myaver(A,B,C,aver)
!DEC$ ATTRIBUTES C, DECORATE, ALIAS:'cf_myaver'::fc_myaver
real A, B, C, aver
end subroutine
end interface

REAL x, y,z, average
x=100
y=200
z=300
PRINT *, 'three numbers: ', x, y, z
call fc_myaver(x,y,z, average)
PRINT *, 'Average of the five numbers is: ', average
END PROGRAM MAIN
----------------------------------------------------------------------------------------

the aver.cpp is the same as the above. I can compile successfully by

ifort -m32 -c main.f90
g++ -c aver.cpp

ifort -m32 -o mytest aver.o main.o

but when i run ./test, it gave these wrong information:
----------------------------------------------------------------------------------------------
three numbers: 100.0000 200.0000 300.0000
forrtl: severe (174): SIGSEGV, segmentation fault occurred
Image PC Routine Line Source
mytest 00001E1F Unknown Unknown Unknown
mytest 00001FA2 Unknown Unknown Unknown
mytest 00001DFD Unknown Unknown Unknown
mytest 00001D86 Unknown Unknown Unknown
Unknown 00000001 Unknown Unknown Unknown
------------------------------------------------------------------------------------------------

can anyone figure out what is wrong here? many thanks!





0 Kudos
Steven_L_Intel1
Employee
2,074 Views
Remove the C in the ATTRIBUTES directive - that changes everything to pass-by-value.

Let me suggest that you do it this way instead:

subroutine fc_myaver(A,B,C,aver) BIND(C,NAME='cf_myaver')

and remove the !DEC$ ATTRIBUTES line. If this doesn't work, please show the current source for the C routine.

0 Kudos
Reply