Fortran module combine with procedure being accessed in C and vice versa

149 Views Asked by At

I am trying to test Fortran/C mixed language by using module and procedure. I used the base example case from this link: http://cftcc.iccas.ac.cn/upload/doc/ifc/f_ug1/pgwusmod.htm but when I try to modify the code, I start to get the error like

"_initfo_", reference from: _MAIN__ in main.o
ld: symbol(s) not found for architecture x86_64. 

here is my code:

new.F >>
      MODULE EXAMP
      use iso_c_binding
         REAL, bind(C) :: A(3)
         INTEGER I1, I2
         CHARACTER(80) LINE
         TYPE MYDATA
             SEQUENCE
             INTEGER N
             CHARACTER(30) INFO
          END TYPE MYDATA
      END MODULE EXAMP
cnew.c >>
/* C  code accessing module data */
extern float a[3];
extern int examp_mp_i1, examp_mp_i2;
extern char examp_mp_line[80];
//extern void usemodule();
extern struct {
    int n;
    char info[30];
} examp_mp_mydata;

void pythagoras (float *c){
    *c = (float) sqrt(a[0]*a[0] + a[1]*a[1]);
}

void initfo(float *aa){
     *aa = a[0]+a[1]+a[2];
}
main.F >>
! Fortran 95/90 Module including procedure
      MODULE CPROC
        INTERFACE
            SUBROUTINE PYTHAGORAS ( res)
            !DEC$ ATTRIBUTES C :: PYTHAGORAS
            !DEC$ ATTRIBUTES REFERENCE :: res
! res is passed by REFERENCE because its individual attribute
!: overrides the subroutine's C attribute
            REAL res
! a and b have the VALUE attribute by default because
! the subroutine has the C attribute
            END SUBROUTINE
        END INTERFACE
        END MODULE

! Fortran 95/90 Module including procedure
      MODULE CCPROC
        INTERFACE
            SUBROUTINE INITFO (aa)
            REAL aa
            END SUBROUTINE
        END INTERFACE
        END MODULE

        PROGRAM MAIN
        USE EXAMP
! Fortran 95/90 Module including procedure
        USE CPROC
        USE CCPROC
        A(1)=1.0
        A(2)=2.0
        A(3)=3.0
        WRITE(*,*) A(1)
        CALL PYTHAGORAS ( X)
        WRITE(*,*) X

        CALL INITFO(Y)
        WRITE(*,*) Y
        END PROGRAM MAIN

I am using intel compilers. this is what I did to compile:

icc -c cnew.c
ifort -c new.f
ifort -o test main.f new.o cnew.o

I am really new to fortran. I really hope someone can point me to a right direction.

Thanks,

Jing

1

There are 1 best solutions below

8
haraldkl On BEST ANSWER

With Fortran 2003 you would declare the interfaces like this:

  INTERFACE
      SUBROUTINE PYTHAGORAS (res) bind(c, name='pythagoras')
        use iso_c_binding
        real(kind=c_float) :: res
      END SUBROUTINE

      SUBROUTINE initfo (aa) bind(c, name='initfo')
        use iso_c_binding
        real(kind=c_float) :: aa
      END SUBROUTINE
  END INTERFACE

The main point here is the name attribute added to the subroutine declaration, this tells the compiler, which symbol to actually use. Otherwise the name mangling gives you not found entities.

In total this gives: new.f90

MODULE EXAMP
  use iso_c_binding

  REAL(kind=c_float), bind(c) :: A(3)
  INTEGER :: I1, I2
  CHARACTER(80) :: LINE

  TYPE MYDATA
     SEQUENCE
     INTEGER :: N
     CHARACTER(len=30) :: INFO
  END TYPE MYDATA

END MODULE EXAMP

main.f90:

MODULE CPROC
  use iso_c_binding
  INTERFACE
      SUBROUTINE PYTHAGORAS (res) bind(c, name='pythagoras')
        use iso_c_binding
        real(kind=c_float) :: res
      END SUBROUTINE

      SUBROUTINE initfo (aa) bind(c, name='initfo')
        use iso_c_binding
        real(kind=c_float) :: aa
      END SUBROUTINE
  END INTERFACE
END MODULE

PROGRAM MAIN
   USE EXAMP
! Fortran 95/90 Module including procedure
   USE CPROC

   A(1)=1.0
   A(2)=2.0
   A(3)=3.0
   WRITE(*,*) A(1)
   CALL PYTHAGORAS(X)
   WRITE(*,*) X

   CALL INITFO(Y)
   WRITE(*,*) Y
END PROGRAM MAIN

With the c-code unchanged. I would urge you to not use global variables like your a.