• Problem with Fortran calling C

    From Beliavsky@21:1/5 to All on Mon Feb 21 15:47:42 2022
    For the C code in twice.c

    int twice(int i)
    {
    return 2*i;
    }

    and Fortran code in cfunc.f90

    program main
    use iso_c_binding, only: c_int
    implicit none
    integer(c_int) :: i
    interface
    function twice(i) bind(c)
    use, intrinsic :: iso_c_binding
    integer(c_int) :: i
    integer(c_int) :: twice
    end function twice
    end interface
    i = 5
    print*,i,twice(i)
    end program main

    I compile and run on Windows with

    del *.o
    if exist a.exe del a.exe
    gcc -c twice.c
    gfortran -c cfunc.f90
    gfortran -o a.exe twice.o cfunc.o
    if exist a.exe a.exe

    but the output is

    5 1182790712

    What did I do wrong?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From FortranFan@21:1/5 to Beliavsky on Mon Feb 21 17:28:32 2022
    On Monday, February 21, 2022 at 6:47:46 PM UTC-5, Beliavsky wrote:

    ..
    interface
    function twice(i) bind(c)
    use, intrinsic :: iso_c_binding
    integer(c_int) :: i
    integer(c_int) :: twice
    end function twice
    end interface
    ..

    The VALUE attribute is missing in the dummy argument 'i' in the interface block.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Beliavsky@21:1/5 to FortranFan on Mon Feb 21 18:24:28 2022
    On Monday, February 21, 2022 at 8:28:36 PM UTC-5, FortranFan wrote:
    On Monday, February 21, 2022 at 6:47:46 PM UTC-5, Beliavsky wrote:

    ..
    interface
    function twice(i) bind(c)
    use, intrinsic :: iso_c_binding
    integer(c_int) :: i
    integer(c_int) :: twice
    end function twice
    end interface
    ..

    The VALUE attribute is missing in the dummy argument 'i' in the interface block.

    Thanks. As you say, it works when the declaration of i in the interface block is changed to

    integer(c_int), value :: i

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ev. Drikos@21:1/5 to Beliavsky on Tue Feb 22 04:52:36 2022
    On 22/02/2022 01:47, Beliavsky wrote:
    For the C code in twice.c

    int twice(int i)
    {
    return 2*i;
    }

    In alternative, the argument in the C function could be a pointer:

    int twice(int *i)
    {
    return 2**i; !In Fortran, it prints 2*i, not 2 ͥ
    }

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Beliavsky@21:1/5 to All on Tue Feb 22 05:59:50 2022
    In my Fortran codes I specify the KIND of real variables but not integer variables. For compatibility with C it is
    safer to declare integers as integer(c_int), but are there platforms where such an integer is distinct from the
    default integer? In my code above if I replace integer(c_int) with integer and get rid of the "use iso_c_binding" statements,
    it still works.

    (Thanks to Ev. Drikos for his comment regarding pointers.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Thomas Koenig@21:1/5 to Beliavsky on Tue Feb 22 17:06:25 2022
    Beliavsky <beliavsky@aol.com> schrieb:
    For the C code in twice.c

    int twice(int i)
    {
    return 2*i;
    }

    and Fortran code in cfunc.f90

    program main
    use iso_c_binding, only: c_int
    implicit none
    integer(c_int) :: i
    interface
    function twice(i) bind(c)
    use, intrinsic :: iso_c_binding
    integer(c_int) :: i
    integer(c_int) :: twice
    end function twice
    end interface
    i = 5
    print*,i,twice(i)
    end program main

    If you compile this with gfortran with -fc-prototypes,
    you will get a valid C prototype for this function:

    $ gfortran -fsyntax-only -fc-prototypes a.f90
    #include <stddef.h>
    #ifdef __cplusplus
    #include <complex>
    #define __GFORTRAN_FLOAT_COMPLEX std::complex<float>
    #define __GFORTRAN_DOUBLE_COMPLEX std::complex<double>
    #define __GFORTRAN_LONG_DOUBLE_COMPLEX std::complex<long double>
    extern "C" {
    #else
    #define __GFORTRAN_FLOAT_COMPLEX float _Complex
    #define __GFORTRAN_DOUBLE_COMPLEX double _Complex
    #define __GFORTRAN_LONG_DOUBLE_COMPLEX long double _Complex
    #endif

    int twice (int *i);

    #ifdef __cplusplus
    }
    #endif

    Include this as a header in your C program, and your C compiler
    will complain.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From James Van Buskirk@21:1/5 to All on Tue Feb 22 09:16:15 2022
    "Beliavsky" wrote in message news:d5312537-6c84-4eaa-be4b-3d26d6253d2en@googlegroups.com...

    In my Fortran codes I specify the KIND of real variables but not integer variables. For compatibility with C it is
    safer to declare integers as integer(c_int), but are there platforms where such an integer is distinct from the
    default integer? In my code above if I replace integer(c_int) with integer and get rid of the "use iso_c_binding" statements,
    it still works.

    With ifort you need the bind('C)' clause, but not in gfortran provided the names
    match, perhaps via a *.DEF file. There is no guarantee that Fortran default integer is the same as C int, but it's pretty likely that it will be. One incompatibility that I have noticed is that Windows ultimately defines
    DWORD as unsigned long which is 32 bits in MSVC++ but then cygwin defines unsigned long as 64 bits, so that messes up your Fortran module for Win32
    API
    interoperability.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Nagle@21:1/5 to All on Tue Feb 22 09:45:23 2022
    Hi,

    On Feb 21, 2022, Beliavsky wrote
    (in article<22b98749-9d21-43b5-8d59-596533b35fc4n@googlegroups.com>):

    For the C code in twice.c

    int twice(int i)
    {
    return 2*i;
    }

    and Fortran code in cfunc.f90

    program main
    use iso_c_binding, only: c_int
    implicit none
    integer(c_int) :: i
    interface
    function twice(i) bind(c)
    use, intrinsic :: iso_c_binding
    integer(c_int) :: i
    integer(c_int) :: twice
    end function twice
    end interface
    i = 5
    print*,i,twice(i)
    end program main

    I compile and run on Windows with

    del *.o
    if exist a.exe del a.exe
    gcc -c twice.c
    gfortran -c cfunc.f90
    gfortran -o a.exe twice.o cfunc.o
    if exist a.exe a.exe

    but the output is

    5 1182790712

    What did I do wrong?

    My guess is, add value to the dummy argument declaration
    in the interface block.

    So --> integer(c_int) :: i
    becomes --> integer(c_int), value :: i

    Let me know how it goes . . .

    --
    Cheers!

    Dan Nagle

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)