Search code examples
cvisual-studio-2010fortranreleasemixed-mode

Mixed programming failed in release but succeeded in debug


In my compiler a function named "func" will be renamed as _FUNC@* after compiling in fortran. And if a c code use _stdcall calling convention, then the function name, e.g. Ab, will be renamed as _Ab@* after compiling. So this can lead to a concise method for mixed programming between fortran and c. The following is my code. source1.f90

program main
implicit none
call subprint()
read(*,*)
endprogram

ccode.c

#include <stdio.h>
#ifdef _cplusplus
extern "C" {
#endif
  void _stdcall SUBPRINT()
{printf("hello the world\n");}
#ifdef _cplusplus
}

My platform is win 7 and vs2010 is used. Compliler is visual c++. The ccode.c will generate a .lib and the fortran project will use it. And this will run successfully in debug mode. But when I changed the project into release mode, errors would occur. The errors are the main function in Source1.f90 can not find out the _SUBPRINT. Note that I have already generated the .lib in the release mode and add it to the fortran project.

Another method for mixed programming is using _cdecl calling convention. The following codes will run successfully in both debug and release mode.

module abc
  interface
    subroutine subprint()
      !dec$ attributes C,alias:'_subprint'::subprint
    end subroutine
  end interface
end module

program main
  use abc
   implicit none
   call subprint()
   read(*,*)
endprogram

Here is the c code. The default calling convention is just _cdecl.

#ifdef _cplusplus
extern "C" {
#endif
 void  subprint()
 {printf("hello the world\n");}
#ifdef _cplusplus
}
#endif

Why this happened? I put all these codes in the same solution. So the configuration is the same.


Solution

  • First, note that your C function is SUBPRINT not subprint, that DOES matter even inside C.

    Second, you should use __cplusplus, not _cplusplus

    Third, just use modern Fortran for interoperability with C:

    c.cc:

    #include <stdio.h>
    #ifdef __cplusplus
    extern "C" {
    #endif
      void subprint(){
       printf("hello the world\n");
      }
    #ifdef __cplusplus
    }
    #endif
    

    f.f90:

    program main
    implicit none
    
    interface
      subroutine subprint() bind(C,name="subprint")
      end subroutine
    end interface
    
    call subprint()
    read(*,*)
    endprogram
    

    gfortran c.cc f.f90

    ./a.out
    hello the world