# Iso\_c\_binding: How to set double C pointer (an array) with a pointer to a Fortran array

**URL:** <https://fortran-lang.discourse.group/t/iso-c-binding-how-to-set-double-c-pointer-an-array-with-a-pointer-to-a-fortran-array/4923>\
**Category:** Uncategorized\
**Created:** [December 19, 2022, 9:50pm UTC](https://fortran-lang.discourse.group/t/iso-c-binding-how-to-set-double-c-pointer-an-array-with-a-pointer-to-a-fortran-array/4923 "2022-12-19T21:50:54Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![giraffe](https://avatars.discourse-cdn.com/v4/letter/g/f1d935/32.png) [@giraffe](https://fortran-lang.discourse.group/u/giraffe)\
**Post date:** [December 19, 2022, 9:50pm UTC](https://fortran-lang.discourse.group/t/iso-c-binding-how-to-set-double-c-pointer-an-array-with-a-pointer-to-a-fortran-array/4923/1 "2022-12-19T21:50:54Z")

</div>

I have pre-existing code that I am modifying to use the Fortran iso\_c\_binding standard. I’d like to know how many ways can you do it.

The below program compiles perfectly without any warnings using the iso\_c\_binding standard but doesn’t work.

Basically originally, on the Fortran side I had an integer defined. This integer got storage for an array via a C malloc. I have a similar variable (but a real) on the Fortran side which gets set to many values. The real is used to set values in what used to be an integer using C. How do I modify the below program to do this with iso\_c\_binding? Does the Fortran and/or C code have to change?

File main.f90:

```auto
       program main
       use the_interface
       use iso_c_binding, only : c_int,c_ptr,c_loc

       implicit none
       type(myint), pointer :: intvar
   
       type(c_ptr), pointer :: value_ptr

       type(real), allocatable, target :: value(:)
       type(c_ptr) :: myint_ptr 

       integer ans,i

       allocate(value(10),value_ptr)

       value_ptr = c_loc(value)

       do i = 1,10
         value(i) = real((i-1) * 3 + (i-1),4)
       end do

       ans = get_storage(myint_ptr)
       ans = set_source(myint_ptr,value_ptr)

       ans = print_source(myint_ptr)
       end program main

```

File test.c:

```auto
#include <stdio.h>
#include <stdlib.h>

typedef int int_type;

struct myint {
   int value;
};

#define NUM 10

int get_storage_ (int_type **dest)  
{
  *dest = (int_type *)malloc(NUM * sizeof(int_type));

  if (!*dest) {
      return -1;
  }

  return 0;
}

int set_source_ (struct myint **dest, struct myint *source)
{
  int i;
  int counter = 0;

  for (i = 0;i < NUM;i++)
  {
    /* (*dest + i)->value = i * 3 + i; */
     (*dest + i)->value = (source + i)->value;

    if (!(++counter % 5))
    {
      printf ("\n");
      counter = 0;
    }
  }

  return 0;
}

int print_source_ (struct myint **dest)
{
  int i;
  int counter = 0;
  int errors = 0;

  for (i = 0;i < NUM;i++)
  {
    if (((*dest + i)->value) != (i * 3 + i))
    {
      printf ("Error at %d %d != %d ",i, ((*dest + i)->value),(i * 3 + i));
      errors ++;
    }
    else
    {
      printf ("Value at %d = %d ",i,(*dest + i)->value);
    }

    counter++;

    if (!(counter % 5))
    {
      printf ("\n");
      counter = 0;
    }
  }

  printf ("\n%d values weren't set correctly!\n",errors);
  printf ("%d values were set correctly!\n\n",NUM - errors);

  return 0;
}

```

File the\_interface.f90:

```auto
       module the_interface
       use iso_c_binding, only: c_int, c_ptr,c_float

       type, bind(c) :: myint
         integer(c_int) :: int_tmp
       end type

       type, bind(c) :: myfloat
         real(c_float) :: float_tmp
       end type

         function get_storage(address)bind(c,name="get_storage_")
             import :: c_int, c_ptr, myint
             implicit none
             type(c_ptr), intent(inout) :: address
             integer(c_int) :: get_storage
         end function

         function set_source(address, value)bind(c,name="set_source_")
             import :: c_int, c_ptr, myint
             implicit none
             type(c_ptr), intent(inout) :: address
             type(c_ptr), intent(inout) :: value
             integer(c_int) :: set_source
         end function

         function print_source(address)bind(c,name="print_source_")
             import :: c_int, c_ptr, myint
             implicit none
             type(c_ptr), intent(inout) :: address
             integer(c_int) :: print_source
         end function
       end interface

       end module the_interface

```

Compilation and Run:

```auto
  gcc -g -c test.c -o test.o 
  gfortran -g -c the_interface.f90 -o the_interface.o
  gfortran -g -c main.f90 -o main.o
  gfortran -g main.o test.o -o main.exe -lgfortran
  ./main.exe

```

Output:

Error at 0 38195424 != 0 Error at 1 38195424 != 4 Error at 2 38195424 != 8 Error at 3 38195424 != 12 Error at 4 38195424 != 16 Error at 5 38195424 != 20 Error at 6 38195424 != 24 Error at 7 38195424 != 28 Error at 8 38195424 != 32 Error at 9 38195424 != 36

---

<div class="post-metadata">

**Author:** ![everythingfunctional](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/everythingfunctional/32/176_2.png) [@everythingfunctional](https://fortran-lang.discourse.group/u/everythingfunctional)\
**Post date:** [December 20, 2022, 2:11am UTC](https://fortran-lang.discourse.group/t/iso-c-binding-how-to-set-double-c-pointer-an-array-with-a-pointer-to-a-fortran-array/4923/3 "2022-12-20T02:11:11Z")

</div>

You’re missing an `interface` statement in `the_interface.f90`, which is minor. The real issue is that your argument for `set_source_` is not correct. Modify that function as:

```c
int set_source_ (struct myint **dest, float** source)
{
  int i;
  int counter = 0;

  for (i = 0;i < NUM;i++)
  {
    /* (*dest + i)->value = i * 3 + i; */
     (*dest + i)->value = (*source)[i];

    if (!(++counter % 5))
    {
      printf ("\n");
      counter = 0;
    }
  }

  return 0;
}

```

and I get

```plaintext
$ gcc -g -c test.c -o test.o 
  gfortran -g -c the_interface.f90 -o the_interface.o
  gfortran -g -c main.f90 -o main.o
  gfortran -g main.o test.o -o main.exe -lgfortran
  ./main.exe

Value at 0 = 0 Value at 1 = 4 Value at 2 = 8 Value at 3 = 12 Value at 4 = 16 
Value at 5 = 20 Value at 6 = 24 Value at 7 = 28 Value at 8 = 32 Value at 9 = 36 

0 values weren't set correctly!
10 values were set correctly!

```

---

<div class="post-metadata">

**Author:** ![everythingfunctional](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/everythingfunctional/32/176_2.png) [@everythingfunctional](https://fortran-lang.discourse.group/u/everythingfunctional)\
**Post date:** [December 21, 2022, 10:09pm UTC](https://fortran-lang.discourse.group/t/iso-c-binding-how-to-set-double-c-pointer-an-array-with-a-pointer-to-a-fortran-array/4923/5 "2022-12-21T22:09:15Z")

</div>

Not as written. You might try exploring `bind(c)` derived types as that allows derived types in Fortran to mirror and be interoperable with C structs.

---

<div class="post-metadata">

**Author:** ![FortranFan](https://avatars.discourse-cdn.com/v4/letter/f/96bed5/32.png) [@FortranFan](https://fortran-lang.discourse.group/u/FortranFan)\
**Post date:** [December 21, 2022, 11:44pm UTC](https://fortran-lang.discourse.group/t/iso-c-binding-how-to-set-double-c-pointer-an-array-with-a-pointer-to-a-fortran-array/4923/6 "2022-12-21T23:44:17Z")

</div>

OP has applied the `BIND(C)` clause to the derived type declaration for the C struct’s. Use of `C_F_POINTER` intrinsic module procedure will thus help such as

```fortran
..
call c_f_pointer( cptr=myint_ptr, for=intvar )
..

```

Then work with `intvar` as with any other object instance of a derived type in Fortran.
