# Fortran interface to C struct containing array of structs

**URL:** <https://fortran-lang.discourse.group/t/fortran-interface-to-c-struct-containing-array-of-structs/3700>\
**Category:** Help\
**Created:** [June 8, 2022, 4:55pm UTC](https://fortran-lang.discourse.group/t/fortran-interface-to-c-struct-containing-array-of-structs/3700 "2022-06-08T16:55:04Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![general\_rishkin](https://avatars.discourse-cdn.com/v4/letter/g/a9a28c/32.png) [@general\_rishkin](https://fortran-lang.discourse.group/u/general_rishkin)\
**Post date:** [June 8, 2022, 4:55pm UTC](https://fortran-lang.discourse.group/t/fortran-interface-to-c-struct-containing-array-of-structs/3700/1 "2022-06-08T16:55:04Z")

</div>

How do you write an Fortran interface for a C struct that contains other arrays of structs?

I wrote a small test to understand how to interface Fortran to a C struct that contains an array(s) of structs. This was to understand why a library I am wrapping using Fortran keeps seg faulting.

In this particular test, the derived type on the Fortran side does not print the same values as the `C` side!

This is the C side:  
**aos.h**

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

struct Foo_ {                
  float pos[2];           
  float cutoff;           
};
typedef struct Foo_ Foo;

struct Bar_ {             
  float pos[2];        
  float centre;        
};
typedef struct Bar_ Bar;

struct FooBar_ {          
  int maxg;   
  int* gorder; 
  Foo f[2];   
  Bar b[2];   
};
typedef struct FooBar_ FooBar;

void init_default_values(FooBar* fb);

```

**aos.c**

```auto
#include "aos.h"

void init_default_values(FooBar* fb) {
  fb = malloc( sizeof(FooBar) );

  fb->maxg = 1;
  fb->gorder = malloc( sizeof(int) );
  *(fb->gorder) = 2;

  printf( "fb->maxg = %d\n", fb->maxg );
  printf( "fb->gorder = %d\n", *(fb->gorder) );

  for (int i = 0; i < 2; ++i) {
    for (int j = 0; j < 2; ++j) {
      fb->f[i].pos[j] = i+j*2;
      printf( "fb->f[%d].pos[%d] = %f\n", i, j, fb->f[i].pos[j] );
    }
  }
}

```

Here is my Fortran attempt:  
**faos.f90**

```auto
module mod_aos
  use iso_c_binding
  use iso_fortran_env, only: f32 => real32, f64 => real64
  implicit none

  type, bind(c) :: Foo
    real(f32) :: pos(2)
    real(f32) :: cutoff
  end type Foo

  type, bind(c) :: Bar
    real(f32) :: pos(2)
    real(f32) :: centre
  end type Bar

  type, bind(c) :: FooBar
    integer(c_int) :: maxg
    type(c_ptr) :: gorder
    type(Foo) :: f(2)
    type(Bar) :: b(2)
  end type FooBar

  interface
    subroutine init_default_values( fb ) bind(c, name="init_default_values")
      import:: FooBar
      type(FooBar), intent(inout) :: fb
    end subroutine init_default_values
  end interface
  
contains  
end module mod_aos

program main
  use iso_c_binding
  use mod_aos
  implicit none

  type(FooBar) :: fb

  print *, "======"
  print *, "C SIDE"
  print *, "======"
  call init_default_values( fb )

  print *, ""
  print *, "============"
  print *, "FORTRAN SIDE"
  print *, "============"
  print *, "fb%maxgeom = ", fb%maxg ! Should be 1
  print *, "fb%gorder = ", fb%gorder ! Should be 2
  print *, "fb%f%pos = ", fb%f(1)%pos ! Should be [0.0, 2.0]
  print *, "fb%f%pos = ", fb%f(2)%pos ! Should be [1.0, 3.0]
end program main

```

Here is the output. notice that the Fortran side prints the wrong values (random values):

> # ====== C SIDE
> 
> fb-\>maxg = 1  
> fb-\>gorder = 2  
> fb-\>f[0].pos[0] = 0.000000  
> fb-\>f[0].pos[1] = 2.000000  
> fb-\>f[1].pos[0] = 1.000000  
> fb-\>f[1].pos[1] = 3.000000
> 
> # ============ FORTRAN SIDE
> 
> fb%maxgeom = 0  
> fb%gorder = 0  
> fb%f%pos = 2.80259693E-45 0.00000000  
> fb%f%pos = -0.00000000 0.00000000

---

<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:** [June 8, 2022, 5:14pm UTC](https://fortran-lang.discourse.group/t/fortran-interface-to-c-struct-containing-array-of-structs/3700/2 "2022-06-08T17:14:48Z")

</div>

> [@general\_rishkin](#):
>
> ```auto
> fb = malloc( sizeof(FooBar) );
> 
> ```

Retry after removing this instruction, there is no need to malloc the reference to the struct on the C side.

---

<div class="post-metadata">

**Author:** ![general\_rishkin](https://avatars.discourse-cdn.com/v4/letter/g/a9a28c/32.png) [@general\_rishkin](https://fortran-lang.discourse.group/u/general_rishkin)\
**Post date:** [June 8, 2022, 7:00pm UTC](https://fortran-lang.discourse.group/t/fortran-interface-to-c-struct-containing-array-of-structs/3700/3 "2022-06-08T19:00:48Z")

</div>

Thanks @FortranFan.

---

<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:** [June 8, 2022, 8:52pm UTC](https://fortran-lang.discourse.group/t/fortran-interface-to-c-struct-containing-array-of-structs/3700/4 "2022-06-08T20:52:15Z")

</div>

> [@general\_rishkin](#):
>
> ```auto
> use iso_fortran_env, only: f32 => real32, f64 => real64
> implicit none
> 
> type, bind(c) :: Foo
> real(f32) :: pos(2)
> 
> ```

@general_rishkin , you will note a `pedantic` consideration will be to use the `c_float` and `c_double` named constants from `iso_c_binding` standard intrinsic module:

```auto
use iso_c_binding, only: f32 => c_float, f64 => c_double

```

The above would appear adequate for the simple example you show. For the actual code, perhaps extend the list as needed due to `ONLY` clause (or other options with the `USE` statement).
