Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29264 Discussions

Problem in passing Integer scalar variable from Fortran to C

Ashutosh_S_Londhe1
1,675 Views

Hi,

I am working on OPS-DSL, which is DSL framework for auto-generation of parallel codes for structured grid applications.
In Fortran side we have subroutine which are used to pass address of an integer scalar variable which will be stored in char pointer in C side.
This is the  C bind function
https://github.com/OP-DSL/OPS/blob/bf90f065fc7f1271a9aa0c1528c9d3dc0dcb8c28/ops/fortran/src/ops_for_declarations.F90#L374C8-L383C35 

 

 function ops_arg_gbl_c ( data, dim, size, acc ) BIND(C,name='ops_arg_gbl_char')
    use, intrinsic :: ISO_C_BINDING
    import :: ops_arg

    type(ops_arg) :: ops_arg_gbl_c

    type(c_ptr), value :: data
    integer(kind=c_int), value :: dim, size
    integer(kind=c_int), value :: acc
end function ops_arg_gbl_c

 

and related C function is
https://github.com/OP-DSL/OPS/blob/bf90f065fc7f1271a9aa0c1528c9d3dc0dcb8c28/ops/c/src/core/ops_lib_core.cpp#L1074 

 

ops_arg ops_arg_gbl_char(char *data, int dim, int size, ops_access acc) {
  return ops_arg_gbl_core(data, dim, size, acc);
}

 


and we have interface for transferring integer scalars or arrays from Fortran 

 

interface ops_arg_gbl
    module procedure ops_arg_gbl_int_scalar, ops_arg_gbl_int_1dim, 
end interface ops_arg_gbl

type(ops_arg) function ops_arg_gbl_int_scalar(data, dim, typ, access)
    use, intrinsic :: ISO_C_BINDING
    implicit none
    integer(4), target :: data
    integer(kind=c_int) :: dim
    character(kind=c_char,len=*) :: typ
    integer(kind=c_int) :: access

    ! warning: access is in FORTRAN style, while the C style is required here
    ops_arg_gbl_int_scalar = ops_arg_gbl_c( c_loc(data) , dim, 4, access-1 )

  end function ops_arg_gbl_int_scalar

type(ops_arg) function ops_arg_gbl_int_1dim(data, dim, typ, access)
    use, intrinsic :: ISO_C_BINDING
    implicit none
    integer(4), dimension(*), target :: data
    integer(kind=c_int) :: dim
    character(kind=c_char,len=*) :: typ
    integer(kind=c_int) :: access

    ! warning: access is in FORTRAN style, while the C style is required here
    ops_arg_gbl_int_1dim = ops_arg_gbl_c( c_loc(data) , dim, 4, access-1 )

  end function ops_arg_gbl_int_1dim

 


so when we call something like this

 

ops_arg_gbl(dummy_int_arr, 4, "integer(kind=4)", OPS_READ)

 

where we want to transfer integer array from fortran of size 4 elements, and then rertieve the content of it later by converting char_ptr to correct integer pointer, we get correct values.

but when trying scalar varaible, it doesnt work. We get wrong values when we try convert the char_ptr back to Fortran integer pointer and retrieve the content pointed by the address in char_ptr

 

ops_arg_gbl(int_var, 1, "integer(kind=4)", OPS_READ)

 


any idea what is wrong here. 



 

Labels (2)
0 Kudos
4 Replies
jimdempseyatthecove
Honored Contributor III
1,633 Views

What is type(ops_arg)?

 

I am not sure what happens if "type ops_arg" is not equivalent to (same sizeof as) a scalar (character, integer(1,2,4,8), real(4,8))

Maybe Steve L can comment on this.

 

What I suggest you do replace the function with a subroutine, and pass in the address of (reference to) the type(ops_arg).

 

See what happens

 

FWIW, I have written some interfaces to C code that interfaces with the HDF5 library

INTERFACE
...(cut) ...
  
        function HDF5_Read_Attribute_Integer(Place_c, Name_c, Value) bind(C,NAME='HDF5_Read_Attribute_Integer') result(ret)
            USE, INTRINSIC :: ISO_C_BINDING
            use H5FORTRAN_TYPES
            use H5global
            implicit none
            type(C_PTR), value :: Place_c, Name_c
            integer :: Value
            integer :: ret
        end function HDF5_Read_Attribute_Integer
  
        function HDF5_Write_Attribute_Integer_Array(Place_c, Name_c, Array, rank, dims) bind(C,NAME='HDF5_Write_Attribute_Integer_Array') result(ret)
            USE, INTRINSIC :: ISO_C_BINDING
            use H5FORTRAN_TYPES
            use H5global
            implicit none
            type(C_PTR), value :: Place_c, Name_c, Array
            integer, value :: rank
            type(C_PTR), value :: dims
            integer :: ret
        end function HDF5_Write_Attribute_Integer_Array
...(cut) ...
END INTERFACE

In my case, the return is a scalar (error code)

Those are examples of passing a scalar, and array, into an HDF5 shell function (which in turn calls the HDF5 C++ code).

 

Jim Dempsey

 

0 Kudos
Ashutosh_S_Londhe1
1,603 Views

Hi Jim,

OPS_ARG is a structure in C++ and we have BIND type in Fortran as well.
C side
https://github.com/OP-DSL/OPS/blob/bf90f065fc7f1271a9aa0c1528c9d3dc0dcb8c28/ops/c/include/ops_lib_core.h#L501 
Fortran side
https://github.com/OP-DSL/OPS/blob/bf90f065fc7f1271a9aa0c1528c9d3dc0dcb8c28/ops/fortran/src/ops_for_declarations.F90#L125

if i declare another variable with attribute target and then pass it ops_arg_gbl, it works

the original variable has parameter attribute associated with it

integer(kind=4), parameter :: nxglbl=128

ops_arg_gbl(nxglbl, 1, "integer(kind=4)", OPS_READ)  ! doesnt work

-------------------------------------------
integer(kind=4), parameter :: nxglbl=128
integer(kind=4), target :: nxglbl_target
nxglbl_target = nxglbl

ops_arg_gbl(nxglbl_target, 1, "integer(kind=4)", OPS_READ)  ! works
0 Kudos
jimdempseyatthecove
Honored Contributor III
1,560 Views
integer(kind=4), parameter :: nxglbl=128

ops_arg_gbl(nxglbl, 1, "integer(kind=4)", OPS_READ)  ! doesnt work
**** if ops_arg_gbl is a function
**** the above statement is in error as there is no left hand side=
**** if ops_arg_gbl is a function
**** there is no call keyword
-------------------------------------------
integer(kind=4), parameter :: nxglbl=128
integer(kind=4), target :: nxglbl_target
nxglbl_target = nxglbl

ops_arg_gbl(nxglbl_target, 1, "integer(kind=4)", OPS_READ)  ! works
**** if ops_arg_gbl is a function
**** the above statement is in error as there is no left hand side=
**** if ops_arg_gbl is a function
**** there is no call keyword

If your actual code is different, please include a complete code snip.

 

Assuming missing "call" or "something=" what I see as a significant difference is not only the target, but also one argument is a parameter.

The parameter may be the cause for the "bug"

 

Jim Dempsey

0 Kudos
FortranFan
Honored Contributor III
1,575 Views

@Ashutosh_S_Londhe1 ,

The problem you have encountered is very likely an issue *specific* to the circumstances of your program rather than anything general as implied by your title, "Problem in passing Integer scalar variable from Fortran to C"

You can confirm this using a very simple and silly case as shown below:

  • C "library" code

 

#include <stdio.h>

void Cfunc(int n, char *s) {
   printf("In Cfunc, n = %d; %s\n", n, s);
}

 

  • Fortran calling program

 

   use, intrinsic :: iso_c_binding, only : c_int, c_char, c_null_char
   interface
      subroutine Cfunc( n, s ) bind(C, name="Cfunc")
         import :: c_int, c_char
         integer(c_int), intent(in), value :: n
         character(kind=c_char,len=1), intent(in) :: s(*)
      end subroutine
   end interface
   integer(c_int) :: a
   character(kind=c_char,len=:), allocatable :: m
   a = 42 ; m = c_char_"Hello World!" // c_null_char
   call Cfunc( a, m )
end 

 

  • Program behavior on Windows OS in a console setting using Intel Fortran compiler

 

C:\temp>cl /c /W3 /EHsc c.c
Microsoft (R) C/C++ Optimizing Compiler Version 19.36.32537 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

c.c

C:\temp>ifx /c /free /standard-semantics p.f
Intel(R) Fortran Compiler for applications running on Intel(R) 64, Version 2024.1.0 Build 20240308
Copyright (C) 1985-2024 Intel Corporation. All rights reserved.


C:\temp>link p.obj c.obj /subsystem:console /out:p.exe
Microsoft (R) Incremental Linker Version 14.36.32537.0
Copyright (C) Microsoft Corporation.  All rights reserved.


C:\temp>p.exe
In Cfunc, n = 42; Hello World!

C:\temp>

 

 So you should expect the same response in your environment using the above code by following your OS-specific steps and the C companion processor with Intel Fortran compiler, of course.

You can then review this code vis-a-vis your actual code and look for any root-cause(s), as to the problem you face.

Note for any further help from any reader here, you will likely need to provide a minimal working example (MWE).

0 Kudos
Reply