Search code examples
cfortran

Calling C Code from FORTRAN


Given Microsoft FORTRAN 5.1 and Microsoft C/C++ 14.0, along with the linker that comes with that version of FORTRAN (that must be used for other dependencies) how do I create a C function and call it from the FORTRAN application?


Solution

  • You have two choices.
    1) I can show with example

    FORTRAN

    program ftest
    use iso_c_bindings
    implicit none
    interface
    function saythis(a) ! should be subroutine if saythis returns void
    import :: c_ptr
    type(c_ptr), value :: a
    end function saythis
    end interface
    
    character(len=80), target :: str
    type(c_ptr) cstr
    integer :: r
    
    str='Hello World From Fortran' // C_NULL_CHAR
    cstr=c_loc(str(1:1))
    r=saythis(cstr)
    

    C/C++

    #ifdef __cpluscplus
    #include &ltl;cstdio>
    using namespace std;
    #else
    #inlcude <stdio.h>
    #endif
    
    #ifdef __GNUC__
    #define FORT(func) func ## _
    #else
    #define FORT(func) __stdcall func ## _
    #endif
    
    #ifdef __cpluscplus
    extern "C" {
    #endif
    __declspec(dllexport) int FORT(sayit)(char* c)
    {
    return printf("%s\n",c);
    }
    
    #ifdef __cpluscplus
    }
    #endif
    

    This works w/gcc toolchain. You'll have to dumpbin on the DLL and fortran object code to see if the names match up correctly.
    The other way is similar:

    //This is for gcc toolchain
    //you'll have to find the symbol conversion yourself
    //I think that Visual Studio converts fortran names
    //to ALL CAPS so instead of func => _func you'll need func => FUNC
    

    FORTRAN

    program ftest
    integer aa,bb,cc
    common/vari/aa,bb,cc
    
    aa=7
    bb=11
    cc=0
    call dosomething
    call dosomethingelse(aa,bb,cc)
    

    C/C++

    #ifdef __cplusplus
    extern "C" {
    #endif
    int _dosomething();
    int _dosomethingelse(int*,int*,int*); //all fortran is pass by reference
    struct { int aa,bb,cc; } vari;
    #ifdef __cplusplus
    }
    #endif
    
    //function def's go here
    //struct vari should be the same memory as common/vari block
    

    COMPILE COMMAND

    $>g++ -c ctest.c <br/>
    $>gfortran -c ftest.f90 <br/>
    $>gfortran *.o -lstdc++ -o test_prog <br/>
    

    Hope this helps