• Operator interface with integer(c_int) and integer(c_long)

    From Thomas Koenig@21:1/5 to All on Sun Apr 17 15:42:15 2022
    The following is slightly simplified.

    I have a C functions I want to interface to, which takes a long
    argument. I also want to have a wrapper function in Fortran
    around it, and operator overloading for it which works for as many
    kinds as possible.

    So,

    use, intrinsic :: iso_c_binding

    interface operator(+)
    module procedure int_add, long_add
    end interface operator(+)

    ! Hopefully, this will be (almost) elided on a 64-bit system.

    recursive function int_add (a, b) result (c)
    type(something), intent(in) :: a
    integer(c_int), intent(in) :: b
    type(something) :: c
    integer(c_long) :: long_b
    long_b = b
    c = long_add (a,long_b)
    end function int_add

    recursive function long_add (a,b) result(c)
    type(something), intent(in) :: a
    integer(c_int), intent(in) :: b
    type(something) :: c
    call some_c_function (a, b, c)
    end function long_add

    On a 64-bit system with 64-bit longs and 32-bit ints, all is fine.
    However, if c_int = c_long, the code is wrong because of an
    ambiguous interface for the operator(+).

    For c_int == c_long, the additional function is not actually needed,
    but I don't see a way to remove it short of all sorts of configure
    hackery and/or preprocessing.

    Any ideas?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From FortranFan@21:1/5 to Thomas Koenig on Sun Apr 17 08:50:50 2022
    On Sunday, April 17, 2022 at 11:42:18 AM UTC-4, Thomas Koenig wrote:

    ..
    Any ideas?

    The standard intrinsic module "ISO_C_BINDING" also includes the named constants of c_int32_t and c_int64_t (and also c_int16_t and c_int8_t).

    Toward generic interfaces these named constants are to be preferred over c_int, c_long, etc. precisely because of the issue encountered in the original post.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Thomas Koenig@21:1/5 to FortranFan on Sun Apr 17 15:51:52 2022
    FortranFan <parekhvs@gmail.com> schrieb:
    On Sunday, April 17, 2022 at 11:42:18 AM UTC-4, Thomas Koenig wrote:

    ..
    Any ideas?

    The standard intrinsic module "ISO_C_BINDING" also includes the named constants of c_int32_t and c_int64_t (and also c_int16_t and c_int8_t).

    Toward generic interfaces these named constants are to be preferred over c_int, c_long, etc. precisely because of the issue encountered in the original post.

    ... which does not help if the binding is specified as "long".

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ron Shepard@21:1/5 to Thomas Koenig on Sun Apr 17 11:24:49 2022
    On 4/17/22 10:51 AM, Thomas Koenig wrote:
    FortranFan <parekhvs@gmail.com> schrieb:
    On Sunday, April 17, 2022 at 11:42:18 AM UTC-4, Thomas Koenig wrote:

    ..
    Any ideas?

    The standard intrinsic module "ISO_C_BINDING" also includes the named constants of c_int32_t and c_int64_t (and also c_int16_t and c_int8_t).

    Toward generic interfaces these named constants are to be preferred over c_int, c_long, etc. precisely because of the issue encountered in the original post.

    ... which does not help if the binding is specified as "long".

    Can you do something like

    if ( c_int32_t .eq. c_long ) then
    ...
    elseif ( c_int64_t .eq. c_long ) then
    ...
    else
    ...

    to straighten out the possibilities? The if statements themselves will
    probably be evaluated at compile time and the dead code will be
    eliminated, so there should be little or no performance penalty for
    doing this.

    The overloading on the fortran side depends on the number of integer
    kinds that you want to support. If you want to support all integer
    kinds, then that itself presents problems with portability. The
    INTEGER_KINDS() array gives you the number and value of the kinds that
    are supported, but then what? How do you write portable code with just
    that information? A preprocessor is one approach, but the language
    itself doesn't do much beyond that array to help.

    $.02 -Ron Shepard

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From FortranFan@21:1/5 to Thomas Koenig on Sun Apr 17 09:27:28 2022
    On Sunday, April 17, 2022 at 11:51:55 AM UTC-4, Thomas Koenig wrote:
    ..
    ... which does not help if the binding is specified as "long".

    It will be better to illustrate the approach I recommend to teams I work with in industry with a fair bit of success using an minimal example.

    Toward this, it will be useful to know about these existing C functions.

    Since C does NOT permit function overloading, I presume they might along the following lines:

    typedef struct t {
    int x;
    } T;
    T foo(T*, int*);
    T bar(T*, long*);

    Is that a fair assumption?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From FortranFan@21:1/5 to FortranFan on Sun Apr 17 09:45:56 2022
    On Sunday, April 17, 2022 at 11:50:52 AM UTC-4, FortranFan wrote:
    On Sunday, April 17, 2022 at 11:42:18 AM UTC-4, Thomas Koenig wrote:

    ..
    Any ideas?

    The standard intrinsic module "ISO_C_BINDING" also includes the named constants of c_int32_t and c_int64_t (and also c_int16_t and c_int8_t).

    Toward generic interfaces these named constants are to be preferred over c_int, c_long, etc. precisely because of the issue encountered in the original post.

    Shown below is what I mean: @Thomas Koening and anyone else interested can try out to see my recommendation:

    1. C code, file c.c
    #include <stdio.h>
    typedef struct t {
    int x;
    } T;
    T foo(T*, int*);
    T bar(T*, long*);

    T foo(T* a, int* b) {
    T r;
    r.x = a->x + *b;
    printf("In foo: a, b, r = %d, %d, %d\n", a->x, *b, r.x);
    return r;
    }

    T bar(T* a, long* b) {
    T r;
    r.x = a->x + *b;
    printf("In bar: a, b, r = %d, %d, %d\n", a->x, *b, r.x);
    return r;
    }

    2. Fortran code, file p.f90
    module m
    use, intrinsic :: iso_c_binding, only : c_int, c_int32_t, c_int64_t
    type, bind(C) :: t
    integer(c_int) :: x
    end type

    interface
    function foo( a, b ) result(r) bind(C, name="foo")
    import :: c_int32_t, t
    ! Argument list
    type(t), intent(in) :: a
    integer(c_int32_t), intent(in) :: b
    ! Function result
    type(t) :: r
    end function
    function bar( a, b ) result(r) bind(C, name="bar")
    import :: c_int64_t, t
    ! Argument list
    type(t), intent(in) :: a
    integer(c_int64_t), intent(in) :: b
    ! Function result
    type(t) :: r
    end function
    end interface
    interface operator(+)
    procedure foo;
    procedure bar;
    end interface
    end module
    use m
    use, intrinsic :: iso_c_binding, only : c_long
    type(t) :: u
    integer(c_long) :: v
    u%x = 41 ; v = 1
    u = u + v
    print *, "u%x = ", u%x, "; expected is 42."
    end

    3. Program response using gfortran on 32-bit Windows OS:
    c:\temp>gfortran -c c.c

    C:\temp>gfortran -c p.f90

    C:\temp>gfortran p.o c.o -o p.exe

    C:\temp>p.exe
    In foo: a, b, r = 41, 1, 42
    u%x = 42 ; expected is 42.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Thomas Koenig@21:1/5 to Ron Shepard on Sun Apr 17 17:17:55 2022
    Ron Shepard <nospam@nowhere.org> schrieb:
    On 4/17/22 10:51 AM, Thomas Koenig wrote:
    FortranFan <parekhvs@gmail.com> schrieb:
    On Sunday, April 17, 2022 at 11:42:18 AM UTC-4, Thomas Koenig wrote:

    ..
    Any ideas?

    The standard intrinsic module "ISO_C_BINDING" also includes the named constants of c_int32_t and c_int64_t (and also c_int16_t and c_int8_t).

    Toward generic interfaces these named constants are to be preferred over c_int, c_long, etc. precisely because of the issue encountered in the original post.

    ... which does not help if the binding is specified as "long".

    Can you do something like

    if ( c_int32_t .eq. c_long ) then
    ...
    elseif ( c_int64_t .eq. c_long ) then
    ...
    else

    Unfortunately, this does not work for defining an interface for
    operator(+).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Thomas Koenig@21:1/5 to FortranFan on Sun Apr 17 17:16:20 2022
    FortranFan <parekhvs@gmail.com> schrieb:
    On Sunday, April 17, 2022 at 11:51:55 AM UTC-4, Thomas Koenig wrote:
    ..
    ... which does not help if the binding is specified as "long".

    Toward this, it will be useful to know about these existing C functions.

    The prototype is (paraphrased)

    foo_add (foo_type *, foo_type * const, long);

    where foo_add is from an external library I have no control over.

    On the Fortran side, I would like to do

    type(foo_type) :: a, b
    b = a + 1

    where addition is meaningful for foo_type, and I would also like
    to be able to do have another kind of integer, so this can be used
    using operators following normal Fortran rules (as far as possible).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From FortranFan@21:1/5 to Thomas Koenig on Sun Apr 17 10:28:46 2022
    On Sunday, April 17, 2022 at 1:16:23 PM UTC-4, Thomas Koenig wrote:
    FortranFan schrieb:
    On Sunday, April 17, 2022 at 11:51:55 AM UTC-4, Thomas Koenig wrote:
    ..
    ... which does not help if the binding is specified as "long".

    Toward this, it will be useful to know about these existing C functions.
    The prototype is (paraphrased)

    foo_add (foo_type *, foo_type * const, long);

    where foo_add is from an external library I have no control over.

    On the Fortran side, I would like to do

    type(foo_type) :: a, b
    b = a + 1

    where addition is meaningful for foo_type, and I would also like
    to be able to do have another kind of integer, so this can be used
    using operators following normal Fortran rules (as far as possible).

    Perhaps you will see my minimal but fully working example upthread: https://groups.google.com/g/comp.lang.fortran/c/JgeUMfTHIuA/m/so1jiycPEgAJ

    Give it a try on 64-bit Linux where, if I understood correctly, GCC uses 64-bit integer for long.; I don't have access to Linux. Then compare the program response relative to what's shown below.

    Also, the above example hopefully also shows how to address the need, "I would also like to be able to do have another kind of integer, so this can be used > using operators following normal Fortran rules (as far as possible)."

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Thomas Koenig@21:1/5 to FortranFan on Sun Apr 17 17:43:33 2022
    FortranFan <parekhvs@gmail.com> schrieb:
    On Sunday, April 17, 2022 at 1:16:23 PM UTC-4, Thomas Koenig wrote:
    FortranFan schrieb:
    On Sunday, April 17, 2022 at 11:51:55 AM UTC-4, Thomas Koenig wrote:
    ..
    ... which does not help if the binding is specified as "long".

    Toward this, it will be useful to know about these existing C functions. >> The prototype is (paraphrased)

    foo_add (foo_type *, foo_type * const, long);

    where foo_add is from an external library I have no control over.

    On the Fortran side, I would like to do

    type(foo_type) :: a, b
    b = a + 1

    where addition is meaningful for foo_type, and I would also like
    to be able to do have another kind of integer, so this can be used
    using operators following normal Fortran rules (as far as possible).

    Perhaps you will see my minimal but fully working example upthread: https://groups.google.com/g/comp.lang.fortran/c/JgeUMfTHIuA/m/so1jiycPEgAJ

    Unfortunately, this does not work for what I had in mind (which I
    also explained upthread). The problem I am trying to address is
    on the Fortran side, in the interface block, when c_int == c_long.

    So, I guess there is no way to do what I need in the Fortran language,
    and configure / preprocessor hackery it shall be.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From FortranFan@21:1/5 to Thomas Koenig on Sun Apr 17 11:19:39 2022
    On Sunday, April 17, 2022 at 1:43:36 PM UTC-4, Thomas Koenig wrote:

    ..
    Unfortunately, this does not work for what I had in mind (which I
    also explained upthread). The problem I am trying to address is
    on the Fortran side, in the interface block, when c_int == c_long.

    So, I guess there is no way to do what I need in the Fortran language,
    and configure / preprocessor hackery it shall be.

    Another thing I would try is c_size_t instead of c_int / c_long kinds in the Fortran INTERFACE construct and with a single function definition in that construct:

    module m
    use, intrinsic :: iso_c_binding, only : c_int, c_size_t
    type, bind(C) :: t
    integer(c_int) :: x
    end type
    interface
    function foo( a, b ) result(r) bind(C, name="foo")
    import :: c_size_t, t
    ! Argument list
    type(t), intent(in) :: a
    integer(c_size_t), intent(in) :: b
    ! Function result
    type(t) :: r
    end function
    end interface
    interface operator(+)
    procedure foo
    end interface
    end module
    use, intrinsic :: iso_c_binding, only : clong => c_size_t
    use m
    type(t) :: u
    integer(clong) :: v
    u%x = 41 ; v = 1
    u = u + v
    print *, "u%x = ", u%x, "; expected is 42."
    end

    When on Linux platforms where (c_int == c_long) would be equivalent I think to -m32 option: The above setup with c_size_t should then work on both such platforms where (c_int == c_long) as well as "On a 64-bit system with 64-bit longs and 32-bit ints"
    .

    C:\temp>x86_64-w64-mingw32-gfortran.exe -m32 -c c.c

    C:\temp>x86_64-w64-mingw32-gfortran.exe -m32 -c p.f90

    C:\temp>x86_64-w64-mingw32-gfortran.exe -m32 p.o c.o -o p.exe

    C:\temp>p.exe
    In foo: a, b, r = 41, 1, 42
    u%x = 42 ; expected is 42.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Ruben@21:1/5 to Thomas Koenig on Mon Apr 18 04:21:25 2022
    On Sun, 17 Apr 2022 17:43:33 -0000 (UTC), Thomas Koenig wrote:

    Unfortunately, this does not work for what I had in mind (which I also explained upthread). The problem I am trying to address is on the
    Fortran side, in the interface block, when c_int == c_long.

    So, I guess there is no way to do what I need in the Fortran language,
    and configure / preprocessor hackery it shall be.

    I haven't been following this discussion all that closely, but I think
    that FortranFan had the right idea. The compiler doesn't choose a
    particular module procedure on the basis of the text strings "c_int" or "c_long". It chooses on the basis of the kind values assigned to those
    strings. Therefore, if you write module procedures using all combinations
    of "c_int32_t" and "c_int64_t", one and only one of those procedures will
    be chosen regardless of whether or not c_int == c_long. Doesn't this
    solve your problem?

    D.R.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Thomas Koenig@21:1/5 to David Ruben on Mon Apr 18 05:52:49 2022
    David Ruben <ruben@fbml-cmr.mit.edu> schrieb:
    On Sun, 17 Apr 2022 17:43:33 -0000 (UTC), Thomas Koenig wrote:

    Unfortunately, this does not work for what I had in mind (which I also
    explained upthread). The problem I am trying to address is on the
    Fortran side, in the interface block, when c_int == c_long.

    So, I guess there is no way to do what I need in the Fortran language,
    and configure / preprocessor hackery it shall be.

    I haven't been following this discussion all that closely, but I think
    that FortranFan had the right idea. The compiler doesn't choose a
    particular module procedure on the basis of the text strings "c_int" or "c_long". It chooses on the basis of the kind values assigned to those strings. Therefore, if you write module procedures using all combinations
    of "c_int32_t" and "c_int64_t", one and only one of those procedures will
    be chosen regardless of whether or not c_int == c_long. Doesn't this
    solve your problem?

    I can then chose a module procedure, but it would silently generate
    wrong code if "long" is 32 bits and I am trying to pass a 64-bit
    integer from Fortran.

    As for a runtime check... either such a program should compile, or not.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Thomas Koenig@21:1/5 to FortranFan on Mon Apr 18 08:08:02 2022
    FortranFan <parekhvs@gmail.com> schrieb:
    On Sunday, April 17, 2022 at 1:43:36 PM UTC-4, Thomas Koenig wrote:

    ..
    Unfortunately, this does not work for what I had in mind (which I
    also explained upthread). The problem I am trying to address is
    on the Fortran side, in the interface block, when c_int == c_long.

    So, I guess there is no way to do what I need in the Fortran language,
    and configure / preprocessor hackery it shall be.

    Another thing I would try is c_size_t instead of c_int / c_long
    kinds in the Fortran INTERFACE construct and with a single function definition in that construct:

    This would fail for the code (on the Fortran side) of

    a = b + 1

    when c_size_t does not match Fortran's standard integer.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From FortranFan@21:1/5 to Thomas Koenig on Mon Apr 18 05:13:40 2022
    On Monday, April 18, 2022 at 4:08:05 AM UTC-4, Thomas Koenig wrote:
    FortranFan schrieb:
    ..
    Another thing I would try is c_size_t instead of c_int / c_long
    ..
    This would fail for the code (on the Fortran side) of

    a = b + 1

    when c_size_t does not match Fortran's standard integer.

    See the fully worked out example upthread with c_size_t: https://groups.google.com/g/comp.lang.fortran/c/JgeUMfTHIuA/m/GFMazEQUEgAJ

    Note again in the Fortran standard, no interoperability is indicated of a Fortran "standard integer" with C. To state the obvious, what the standard states is that with a companion C processor, objects of certain types and kinds are interoperable. In
    the case of integer, these of course include kinds such as c_int, c_long, c_int32_t, c_size_t, etc. provided they are consistent with the parameters defined in the companion C processor.

    Thus an instruction such as "a = b + 1" should not be expected to be interoperable to begin with.

    Whereas "a = b + x" can be when 'a', 'b', and 'x' are interoperable,

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From FortranFan@21:1/5 to Thomas Koenig on Mon Apr 18 07:02:17 2022
    On Monday, April 18, 2022 at 9:19:16 AM UTC-4, Thomas Koenig wrote:

    ..
    I have already explained that size_t is not good enough for what I have
    in mind.
    ..
    Of course, a user using c_long will be restricted by the semantics
    of C's long data type.

    Clearly code that uses facilities with standard C and also follows *good practices* will face little to no issues of the kind mentioned in the original post when interoperating with Fortran, here it is assumed the types involved are interoperable as
    indicated in the Fortran standard.

    The good practices aspect involves using types in C that are unambiguous or suffer far less from ambiguity. With signed integers in C, this corresponds to int32_t and int64_t in an overwhelming majority of the use cases. For such integer kinds, the
    Fortran options for interoperation have already been mentioned upthread.

    The `long` data type in C has long been a cause of confusion with many unsuspecting coders, particularly with the upgrade to 64-bit Linux platforms. Our approach is generally to refactor the C code such that the use of this data type is suitably
    replaced with a clear, "modern" option.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Thomas Koenig@21:1/5 to FortranFan on Mon Apr 18 13:19:13 2022
    FortranFan <parekhvs@gmail.com> schrieb:
    On Monday, April 18, 2022 at 4:08:05 AM UTC-4, Thomas Koenig wrote:
    FortranFan schrieb:
    ..
    Another thing I would try is c_size_t instead of c_int / c_long
    ..
    This would fail for the code (on the Fortran side) of

    a = b + 1

    when c_size_t does not match Fortran's standard integer.

    See the fully worked out example upthread with c_size_t: https://groups.google.com/g/comp.lang.fortran/c/JgeUMfTHIuA/m/GFMazEQUEgAJ

    I have already explained that size_t is not good enough for what I have
    in mind.

    Note again in the Fortran standard, no interoperability is
    indicated of a Fortran "standard integer" with C. To state the
    obvious, what the standard states is that with a companion C
    processor, objects of certain types and kinds are interoperable.

    In the case of integer, these of course include kinds such as c_int,
    c_long, c_int32_t, c_size_t, etc. provided they are consistent
    with the parameters defined in the companion C processor.

    Sure.

    And if c_int happens to be the same kind as that of the default
    integer, then the code will work. If not, it will fail.

    Thus an instruction such as "a = b + 1" should not be expected
    to be interoperable to begin with.

    There are two possibilities: The compiler accepts the code
    (if c_int == kind(1) or c_long == 1), then all's well. Or, in
    the unexpeced case that the kind numbers do not match, there is
    a compilation error, and the user can turn to the documentation
    and can then insert 1_c_int or 1_c_long, as required.

    Of course, a user using c_long will be restricted by the semantics
    of C's long data type.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Thomas Koenig@21:1/5 to FortranFan on Mon Apr 18 15:43:04 2022
    FortranFan <parekhvs@gmail.com> schrieb:

    The `long` data type in C has long been a cause of confusion
    with many unsuspecting coders, particularly with the upgrade to
    64-bit Linux platforms. Our approach is generally to refactor the
    C code such that the use of this data type is suitably replaced
    with a clear, "modern" option. > >

    Not possible in this case - the type is fixed (and for good reason,
    too).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ev. Drikos@21:1/5 to Thomas Koenig on Mon Apr 18 19:05:37 2022
    On 18/04/2022 08:52, Thomas Koenig wrote:
    I have a C functions I want to interface to, which takes a long
    argument. I also want to have a wrapper function in Fortran
    around it, and operator overloading for it which works for as many
    kinds as possible.

    ...

    I can then chose a module procedure, but it would silently generate
    wrong code if "long" is 32 bits and I am trying to pass a 64-bit
    integer from Fortran.

    It's the silent generation of wrong code that afraid me in a
    recent discussion about some user defined interfaces: https://groups.google.com/g/comp.lang.fortran/c/Akmj_d0opWE/m/ozWk72OJAgAJ



    ...
    Any ideas?


    Yes :-)

    I've just used the c preprocessor below to avoid making the reply
    longer. One doesn't have to use fixed form code as in the example below.

    Also, my solution (hackery) uses conditional compilation in module M,
    which (I guess) isn't a necessity as well.

    Finally, it doesn't seem to be a simple & straightforward solution.

    ------------------------------------------------------------

    macbook:ops suser$ rm -rf *.mod *.smod *.o p.exe
    macbook:ops suser$ gfc -c -fopenmp m.f90 -o m.o
    macbook:ops suser$ gfc -c sm.F -DN=16 -DS16 -o sm16.o
    macbook:ops suser$ gfc -c sm.F -DN=32 -DS32 -o sm32.o
    macbook:ops suser$ gfc -c sm.F -DN=64 -DS64 -o sm64.o
    macbook:ops suser$ gfc -c sm.F -DN=128 -DS128 -o sm128.o
    macbook:ops suser$ gfc -c p.f90 -o p.o
    macbook:ops suser$ gfc m.o sm16.o sm32.o sm64.o sm128.o p.o -o p.exe macbook:ops suser$ ./p.exe
    macbook:ops suser$
    macbook:ops suser$ rm -rf *.mod *.smod *.o p.exe
    macbook:ops suser$ gfc -c -m32 m.f90 -o m.o
    macbook:ops suser$ gfc -c -m32 sm.F -DN=16 -DS16 -o sm16.o
    macbook:ops suser$ gfc -c -m32 sm.F -DN=32 -DS32 -o sm32.o
    macbook:ops suser$ gfc -c -m32 sm.F -DN=64 -DS64 -o sm64.o
    macbook:ops suser$ gfc -c -m32 p.f90 -o p.o
    macbook:ops suser$ gfc -m32 m.o sm16.o sm32.o sm64.o p.o -o p.exe
    ld: warning: The i386 architecture is deprecated for macOS (remove from
    the Xcode build setting: ARCHS)
    macbook:ops suser$ ./p.exe


    macbook:ops suser$ cat m.f90
    module m
    use, intrinsic :: iso_c_binding

    type :: something
    real :: x, y
    end type something

    interface operator(+)
    module procedure int16_add, int32_add, int64_add
    !$ module procedure int128_add
    end interface operator(+)

    interface

    module function int16_add (a, b) result (c)
    type(something), intent(in) :: a
    integer(c_int16_t), intent(in) :: b
    type(something) :: c
    end function int16_add

    module function int32_add (a, b) result (c)
    type(something), intent(in) :: a
    integer(c_int32_t), intent(in) :: b
    type(something) :: c
    end function int32_add

    module function int64_add (a,b) result(c)
    type(something), intent(in) :: a
    integer(c_int64_t), intent(in) :: b
    type(something) :: c
    end function int64_add

    !$ module function int128_add (a, b) result (c)
    !$ type(something), intent(in) :: a
    !$ integer(c_int128_t), intent(in) :: b
    !$ type(something) :: c
    !$ end function int128_add

    end interface

    end module m

    macbook:ops suser$


    macbook:ops suser$ cat sm.F
    submodule (m) sm N
    use, intrinsic :: iso_c_binding

    contains

    module procedure int N _add
    !type(something), intent(in) :: a
    !integer(c_int S _t), intent(in) :: b
    !type(something) :: c

    integer(c_long) bb
    bb=b !then check if ( bb /= b )
    !call some_c_function (a, bb, c)
    end procedure int N _add

    end submodule sm N


    macbook:ops suser$ cat p.f90
    program test
    use iso_fortran_env
    use, intrinsic :: iso_c_binding
    use m
    implicit none


    integer(c_int16_t) :: c_int16=16;
    integer(c_int32_t) :: c_int32=32;
    integer(c_int64_t) :: c_int64=64;
    integer(c_long) :: a_long =64;

    type (something) st;

    st = st + 1;
    st = st + c_int16;
    st = st + c_int32;
    st = st + c_int64;
    st = st + a_long;

    end

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Thomas Koenig@21:1/5 to Thomas Koenig on Mon Apr 18 16:22:44 2022
    Thomas Koenig <tkoenig@netcologne.de> schrieb:
    FortranFan <parekhvs@gmail.com> schrieb:

    The `long` data type in C has long been a cause of confusion
    with many unsuspecting coders, particularly with the upgrade to
    64-bit Linux platforms. Our approach is generally to refactor the
    C code such that the use of this data type is suitably replaced
    with a clear, "modern" option. > >

    Not possible in this case - the type is fixed (and for good reason,
    too).

    Here's what I came up with.

    I finally got around to setting size of int and long as preprocessor
    variables, -DSIZEOF_INT=4 -DSIZEOF_LONG=8 in a to-be-preprocessed
    Fortran file, and then use

    interface operator(+)
    module procedure add_long, add_long2
    #if SIZEOF_INT < SIZEOF_LONG
    module procedure add_int, add_int2
    #endif
    end interface operator(+)

    (where add_long and add_long2 have are for a + i and i + a,
    respectively) and the same for the procedures themselves.

    A bit hackish, I admit, but it works well enough.

    What could actually solve this is some sort of "weak" interface
    which says "If I specified the same interface before, please
    disregard this one".

    interface operator(+)
    modlue procedure add_long, add_long2
    module procedure, weak: add_int, add_int2
    end interface operator(+)

    which could sort out this kind of problem. I'm not sure that this
    is important enough, and that this idea is well-enough thought out,
    to warrant bothering the comittee about :-)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From gah4@21:1/5 to Thomas Koenig on Mon Apr 18 11:43:01 2022
    On Monday, April 18, 2022 at 9:22:47 AM UTC-7, Thomas Koenig wrote:

    (snip)

    What could actually solve this is some sort of "weak" interface
    which says "If I specified the same interface before, please
    disregard this one".

    Could be nice for all declarations. If I dimension an array twice,
    to the same dimension, ignore the second one. Most languages
    don't do that.

    C #include files often include a test and #ifdef to avoid the problem
    of declaring the same thing twice.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From jfh@21:1/5 to All on Mon Apr 18 22:28:14 2022
    On Tuesday, April 19, 2022 at 6:43:03 AM UTC+12, gah4 wrote:
    On Monday, April 18, 2022 at 9:22:47 AM UTC-7, Thomas Koenig wrote:

    (snip)
    What could actually solve this is some sort of "weak" interface
    which says "If I specified the same interface before, please
    disregard this one".
    Could be nice for all declarations. If I dimension an array twice,
    to the same dimension, ignore the second one. Most languages
    don't do that.

    C #include files often include a test and #ifdef to avoid the problem
    of declaring the same thing twice.

    I would welcome weak interfaces - they would make it easier to write programs to run with both gfortran which has 4 real kinds (precisions 6,15,18,33) in my system and ifort which has 3 (omitting 18).

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