Community
cancel
Showing results for 
Search instead for 
Did you mean: 
marc_b_1
Beginner
361 Views

C++ and Fortran linking

Hello,

I'm trying to link C++ and fortran prorgam together, but I get the following error

/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o: In function `_start':

(.text+0x20): undefined reference to `main'

The main program is fortran, calling a C routine. The linking must be done using C compiler (Because in my work I'm in fact compiling with nvcc (nvidia compiler for cuda) and the linking then can not be done using fortran compiler). I didn't find on the web anything that worked.

Moreover, GNU compiler is working fine (I pasted the test code at the end),

g++  -lstdc++ -g -c add.c
g++ -g -o main main.o add.o -lstdc++ -lgfortran

and then,

 Hola
 a+b =            3           6           9          12          15

But compilation with Intel compiler fails,

ifort -cxxlib -lstdc++ -g -c main.f90
icpc -cxxlib -lstdc++ -g -c add.c
icpc -g -o main main.o add.o -lstdc++ -lifcore 
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
Makefile:12: recipe for target 'main' failed
make: *** [main] Error 1

Does someone know what is wrong with my compilation?

Thank you,

Marc Barbry

The C code (add.c),

#include <stdlib.h>
#include <stdio.h>
#include "add.h"

extern "C" void addition_(int *a, int *b, int *c, int *Np)
{
  int N = *Np;
  int i;

  for (i=0; i<N; i++)
  {
    c = a + b;
  }

}

C header (add.h),

extern "C" void addition_(int *a, int *b, int *c, int *Np);

and Fortran code (main.f90),

program main
  
  implicit none
  integer, allocatable :: a(:), b(:), c(:)
  integer :: i, N

  N = 5
  print*, 'Hola'

  allocate(a(N))
  allocate(b(N))
  allocate(c(N))
  c = 0

  do i=1, N
    a(i) = i
    b(i) = 2*i
  enddo

  call addition(a, b, c, N)

  print*, "a+b = ", c

  deallocate(a)
  deallocate(b)
  deallocate(c)

end program

 

0 Kudos
6 Replies
jimdempseyatthecove
Black Belt
361 Views

use ifort to perform the link of object files where one of which has a Fortran PROGRAM.
Use icpc to link when one of the object files has int main(...

Jim Dempsey

marc_b_1
Beginner
361 Views

Dear Jim,

Thank you for your answer, but as I described it in the original message, I MUST link with the C compiler.

This is because  in my program, I use CUDA and therefore the nvcc compiler, but the nvcc compiler use as well icpc. Unfortunately, using nvcc, one can not use fortran compiler to link the modules because only nvcc has access to the cuda libraries. Linking this program using GNU C compiler is working very well, there is no way to do it as well with Intel compiler?

Marc Barbry

jimdempseyatthecove
Black Belt
361 Views

Two options:

1) Make a C/C++ main, changing your Fortran .f90 file containing PROGRAM into a SUBROUTINE (then call that from the C/C++ main)
2) Build a Hello World Fortran program and generate a map. Examine that for entrypoint:

Hello World on Windows as Win32

 0004:0000142c       ___onexitbegin             0040b42c     <common>
 0004:00001430       ___dyn_tls_init_callback   0040b430     <common>

 entry point at        0001:00002b40

 Static symbols

 0000:ffff1000       .debug$S                   00400000     MSVCRTD:MSVCR120D.dll
 
Then locate 1:2b40

 0001:00002740       __RTC_CheckEsp             00403740 f   MSVCRTD:stack.obj
 0001:00002860       _NtCurrentTeb              00403860 f i MSVCRTD:crtexe.obj
 0001:00002b40       _mainCRTStartup            00403b40 f   MSVCRTD:crtexe.obj
 0001:00002ca0       ?_RTC_AllocaFailure@@YAXPAXPAU_RTC_ALLOCA_NODE@@H@Z 00403ca0 f   MSVCRTD:error.obj
 0001:00002e20       ?_RTC_Failure@@YAXPAXH@Z   00403e20 f   MSVCRTD:error.obj

On the icpc link line, you can specify the entrypoint as _mainCRTStartup

Jim Dempsey

marc_b_1
Beginner
361 Views

The second solution does not seem very portable, no?

Marc Barbry

jimdempseyatthecove
Black Belt
361 Views

The choice of portability (or not) is yours - I am giving you choices.

If you use 1) then (depending on the Fortran code) you may also need to make a one time call at program start to _for_rtl_init_, and at program end _for_rtl_finish_ (if called from C, the "_" may be stripped. Calling those routines may also require libraries from the Fortran collection. The interoperability section of the IVF documentation should discuss this topic.

Jim Dempsey

marc_b_1
Beginner
361 Views

Thank you for your help.

I will think what solution is more adapted for our program.

Marc Barbry

Reply