Find the answer to your Linux question:
Results 1 to 7 of 7
Hello, This is my first post. I hope to be clear with this (this not my native language) =). This is my problem: I want to call a subroutine in ...
  1. #1
    Just Joined!
    Join Date
    Jan 2011
    Posts
    5

    Smile [SOLVED] Calling routines in Fortran modules from C++

    Hello,

    This is my first post. I hope to be clear with this (this not my native language) =).

    This is my problem:

    I want to call a subroutine in Fortran 90 from a c++ code.
    I can do it, when the fortran code have no module.
    But i need to call the subroutine in a fortran code that have an module.

    I have a simple program that shows my problem.
    The Fortran code is:
    Code:
    !add2.f90
    Module add2
    	  Implicit none
          Contains
          subroutine prueba(N,N2)
          integer :: N,N2
          N2 = N*N
          end subroutine prueba
          
          subroutine prueba1(N,N3)
          integer :: N,N3
          N3 = N*N*N
         end subroutine prueba1
          
    End Module add2
    And the c++ code is:
    Code:
    //nada.cpp
    #include <iostream> 
    #include <cmath>
    using namespace std;
     
    extern void __add2_NMOD_prueba(int *N,int *N2);
    int main(){
    	 int n = 2.0;
             int n2,n3 ;     
      
    	__add2_NMOD_prueba(&n,&n2);
    	cout<<"n2 es: "<<n2<<endl;
    	return 0;
    	}
    And for compile, I use gcc:

    Code:
    g++ -O0 -g -c nada.cpp 
    gfortran -O0 -g -frecord-marker=8 -c add2.f90 
    g++ -O0 -g -frecord-marker=8 -o a.test nada.o add2.o -lgfortran
    but, when i link the *.o in the last sentence. I have this error:
    Code:
    nada.o: In function `main':
    /home/cariosr/Programas2011/Pruebas/Pruebas_Fortran/nada.cpp:31: undefined reference to `__add2_NMOD_prueba(int*, int*)'
    collect2: ld returned 1 exit status
    I Dont know where is the problem. Maybe it is in the call of the function. I found that the syntax have this form:
    extern void __namemodule__NMOD_namesubrutine(arg)

    I appreciate any help you can give me.

  2. #2
    Just Joined!
    Join Date
    Mar 2009
    Location
    Norway
    Posts
    52
    try to prefix a *single* underscore (_) not double

  3. #3
    Just Joined!
    Join Date
    Jan 2011
    Posts
    5
    thanks henrikau, for the sugestion, but i have the same problem:

    undefined reference to `_add2_NMOD_prueba'

  4. #4
    Just Joined!
    Join Date
    Mar 2009
    Location
    Norway
    Posts
    52
    Quote Originally Posted by taku View Post
    undefined reference to `_add2_NMOD_prueba'
    Yeah, my bad. Not only was that wrong, it was wrong in several ways:

    1) gfortran normally adds trailing underscore
    2) if the function has an underscore, gfortran will add two
    3) this does not apply when using modules

    What I've discovered so far (but not been able to resolve properly) is that the function is exported as (the fortran-code has only the first of your functions):

    Code:
    $ nm add.o
    00000000 T __add2_MOD_prueba
    So, it looks like the mod-naming is wrong (MOD not NMOD), but the trailing underscore is missing - added to front instead.

    I'm trying to figure out what to pass to ld in order to link this properly, but so far I've been unsuccessful.

    On the other hand, this problem was so interesting that I'm unable to put it aside! (stay tuned...)

    henrik

  5. #5
    Just Joined!
    Join Date
    Mar 2009
    Location
    Norway
    Posts
    52
    hah! got it!

    The problem is that g++ must compile the fortran code as C, not C++. This is done by adding "C" to the prototype

    Code:
    extern "C" { void __add2_MOD_prueba(int *, int *); }
    Now it should link properly

  6. #6
    Just Joined!
    Join Date
    Jan 2011
    Posts
    5
    wooww. thanks a lot!!, henrikau.
    I tried it and it works correctly.

  7. #7
    drl
    drl is offline
    Linux Engineer drl's Avatar
    Join Date
    Apr 2006
    Location
    Saint Paul, MN, USA / CentOS, Debian, Solaris, SuSE
    Posts
    1,117
    Hi.

    I found 2 other solutions, one old, one new.

    The old one is at cfortran.h which transforms calls between c and Fortran. It's a bit messy, but has some advantages. I did get it to work, but only with the Fortran subroutines out of the module. It's possible that with more research the routines encapsulated in the module might be able to be used.

    The new one is a Fortran-2003 feature that is available in gfortran: Interoperable Subroutines and Functions - The GNU Fortran Compiler

    One might also want to look at the c counterpart Interoperation - Using the GNU Compiler Collection (GCC)

    I also got that to work, but again with the Fortran outside the module.

    I think the simple code that henrikau suggested is by far the best solution for the problem at hand, but the others might be useful in different situations.

    Good luck ... cheers, drl

    Note that the call to
    Code:
    __add2_NMOD_prueba(&n,&n2);
    needs to be changed to:
    Code:
    __add2_MOD_prueba(&n,&n2);
    Welcome - get the most out of the forum by reading forum basics and guidelines: click here.
    90% of questions can be answered by using man pages, Quick Search, Advanced Search, Google search, Wikipedia.
    We look forward to helping you with the challenge of the other 10%.
    ( Mn, 2.6.n, AMD-64 3000+, ASUS A8V Deluxe, 1 GB, SATA + IDE, Matrox G400 AGP )

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
...