# Not having expected behaviour in Fortran-C interoperability

**URL:** <https://fortran-lang.discourse.group/t/not-having-expected-behaviour-in-fortran-c-interoperability/5944>\
**Category:** Help\
**Created:** [June 9, 2023, 8:34am UTC](https://fortran-lang.discourse.group/t/not-having-expected-behaviour-in-fortran-c-interoperability/5944 "2023-06-09T08:34:08Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![mEm](https://avatars.discourse-cdn.com/v4/letter/m/90ced4/32.png) [@mEm](https://fortran-lang.discourse.group/u/mEm)\
**Post date:** [June 9, 2023, 8:34am UTC](https://fortran-lang.discourse.group/t/not-having-expected-behaviour-in-fortran-c-interoperability/5944/1 "2023-06-09T08:34:09Z")

</div>

Hi everyone,

I’m not having the expected behavior, surely because I am missing something.

Basically the situation is like:

```auto
! CALLING PROGRAM
integer, target :: ierr = -1
call bsacl_Init(ierr)

! C-interf MODULE PROCEDURE
   module subroutine bsacl_Init(ierr)
      integer, intent(inout), target :: ierr
      call bsaclInit(c_loc(ierr))
   end subroutine

! ACTUAL C-core CODE
void bsaclInit(int *ierr)

```

But at the time I enter the C code, `*ierr` holds random garbage (expecting -1). And even changing it inside bsaclInit(), then exiting bsacl\_Init(), ierr still holds -1, i.e. did not get modified (even though ierr in c-code is).

Shouldn’t `c_loc()` work normally with scalar fortran variables? It looks like is not working as in the C counterpart `bsaclInit(&ierr_);`.

I then changed (for both main Fortran program and interafce module) to `/iface:stdcall`. This led to correct behavior up to `bsacl_Init()`. Then, returning to the main program right after, `ierr` returned to hold -1.

Any advice is more than welcome 🙂

---

<div class="post-metadata">

**Author:** ![PierU](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/pieru/32/1848_2.png) [@PierU](https://fortran-lang.discourse.group/u/PierU)\
**Post date:** [June 9, 2023, 9:04am UTC](https://fortran-lang.discourse.group/t/not-having-expected-behaviour-in-fortran-c-interoperability/5944/2 "2023-06-09T09:04:46Z")

</div>

`cloc(ierr)` returns the address of `ierr`. The Fortran compiler then creates a temporary variable on the stack that contains this address, and then passes the address of the temporary variable. So basically it passes the address of the address of `ierr`, and on the C side you should have

```auto
void bsaclInit(int **ierr)

```

Alternatively, without changing the C interface, your call should be:

```auto
call bsaclInit(ierr)

```

Note that you are assuming that a Fortran `integer` maps to a C `int`. Although true most of time, this is not guaranteed. A more robust code would use the C binding features:

```auto
   subroutine bsacl_Init(ierr)
      use iso_c_binding
      integer, intent(inout) :: ierr
      interface 
          subroutine bsaclInit(ierr) bind(C)
              integer(c_int) :: ierr
          end subroutine
      end interface
      integer(c_int) :: ierr_c
      ierr_c = ierr
      call bsaclInit(ierr_c)
      ierr = ierr_c
   end subroutine

```

---

<div class="post-metadata">

**Author:** ![mEm](https://avatars.discourse-cdn.com/v4/letter/m/90ced4/32.png) [@mEm](https://fortran-lang.discourse.group/u/mEm)\
**Post date:** [June 9, 2023, 9:29am UTC](https://fortran-lang.discourse.group/t/not-having-expected-behaviour-in-fortran-c-interoperability/5944/4 "2023-06-09T09:29:10Z")

</div>

Thanks @PierU , I get it now.  
I was assuming the Fortran compiler was passing the value of the temporary `c_loc(ierr)`, instead of its address. Strange because actually in `bsacl_init()` I was then having the right behavior (after the call, ierr became 0).  
It was at the time of exiting, that in the main program `ierr` returned to hold -1, because at that point, with stdcall, the compiler did a copy (instead of normally passing the address).

Have to study this more.

---

<div class="post-metadata">

**Author:** ![mEm](https://avatars.discourse-cdn.com/v4/letter/m/90ced4/32.png) [@mEm](https://fortran-lang.discourse.group/u/mEm)\
**Post date:** [June 9, 2023, 9:37am UTC](https://fortran-lang.discourse.group/t/not-having-expected-behaviour-in-fortran-c-interoperability/5944/5 "2023-06-09T09:37:47Z")

</div>

In fact, I got it to work with my original approach.

After thinking about it, the problem was in the Fortran procedure interafce bound to the actual C code:

```auto
interface
      subroutine bsaclInit(ierr) bind(c, name="bsaclInit")
         import c_ptr
         type(c_ptr) :: ierr
      end subroutine

```

Of course, here it was passing the address of the temporary.

I had to change to:

```auto
interface
      subroutine bsaclInit(ierr) bind(c, name="bsaclInit")
         import c_ptr
         type(c_ptr), value :: ierr
      end subroutine

```

Thanks @PierU for your suggestion, surely I will keep it in mind !!

---

<div class="post-metadata">

**Author:** ![PierU](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/pieru/32/1848_2.png) [@PierU](https://fortran-lang.discourse.group/u/PierU)\
**Post date:** [June 9, 2023, 10:07am UTC](https://fortran-lang.discourse.group/t/not-having-expected-behaviour-in-fortran-c-interoperability/5944/6 "2023-06-09T10:07:44Z")

</div>

It wasn’t clear if you had an explicit interface or for the C routine. I assumed you were using an implicit interface.

Although describing the interface with `type(c_ptr), value :: ierr` is (I think) equivalent to `integer(c_int) :: ierr`, I prefer the latter: the compiler can check the type of the actual argument when calling the routine, whereas `c_loc()` of virtually any object/type will be OK for the compiler. And it makes clear that the C routine is expecting a pointer to an `int` and not a generic pointer.
