3

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

Jing Yang
  • 33
  • 3

1 Answers1

3

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.

haraldkl
  • 3,809
  • 26
  • 44
  • Thank you for your valuable modifications on my code. It works out perfectly. Can I know the reason why it is a bad idea to use have "a" as a global variable? Also, is the common block in fortran also some kind of global variable? Is it good or bad to have lots common blocks in the code? If it is bad, what suggestions do you have to make the code better and safer? – Jing Yang Sep 28 '15 at 15:33
  • @JingYang Common blocks are obsolete and should not be used in new codes. They can easily give rise to confusion. The modern construct, that in some places could be used to replace it, would be module variables. Global variables are bad because they confuse the reader and are hard to keep track of. Moreover, they might inhibit the compiler to perform optimizations. If you pass around required variables, the flow of data gets much more visible. The limited scope of routines helps both, the reader and the compiler. – haraldkl Sep 28 '15 at 16:17
  • Thank you for your prompt reply. Can you be more specific about how to modify my global variable? Do you mean by passing the "a" into every subroutine that has access of "a" or in the module part, I should put the variable as something like: "real, public :: A(3)" ? – Jing Yang Sep 28 '15 at 17:05
  • Yes, by passing I mean defining it as an argument, like the `res` in your pythagoras routine. – haraldkl Sep 28 '15 at 20:38
  • Thank you for your reply. I learnt so much from you. Can you answer me one more question? Now, I am trying to modify the derived type between C and fortran. I still get the symbol not found error. I have put bind(c) as TYPE, bind(c) :: MYDATA and removed the sequence tag. The C code still doesn't recognize mydata....Any idea on this? – Jing Yang Sep 29 '15 at 03:26
  • @JingYang Are you trying to use the type directly in C? This is not how it works, you would need to define a corresponding struct on the C side. Then you should be able to declare compatible variables on both sides. Though, I don't have any experience with this, I usually stay away from complicated data description to pass between both sides. There are many limitations on the kind of data structures that can be interoperable. Often, you do not need any internal information about the objects on the other side and merely need some handle. This could be done with a pointer. – haraldkl Sep 29 '15 at 06:03
  • @JingYang, I'd recommend you to have a look at these questions: http://stackoverflow.com/q/2758635/577108 and http://stackoverflow.com/q/31672/577108. There are several useful links in the answers there, which might help you to learn more on the topic. The Metcalf book is the definite Fortran reference, I'd say. A good book missing in those threads might be "Introduction to Programming with Fortran: With Coverage of Fortran 90, 95, 2003, 2008 and 77". – haraldkl Sep 29 '15 at 06:17
  • That is very useful!! Thank you very much to keep up with me! I will go take a look at the book. – Jing Yang Sep 29 '15 at 14:27