# Allocate interoperability and C descriptors

**URL:** <https://fortran-lang.discourse.group/t/allocate-interoperability-and-c-descriptors/5088>\
**Category:** Help\
**Created:** [January 26, 2023, 5:04pm UTC](https://fortran-lang.discourse.group/t/allocate-interoperability-and-c-descriptors/5088 "2023-01-26T17:04:01Z")\
**Posts on this page:** 1\
**Showing post:** 9

<div class="post-metadata">

**Author:** ![ivanpribec](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/ivanpribec/32/3290_2.png) [@ivanpribec](https://fortran-lang.discourse.group/u/ivanpribec)\
**Post date:** [January 26, 2023, 11:10pm UTC](https://fortran-lang.discourse.group/t/allocate-interoperability-and-c-descriptors/5088/9 "2023-01-26T23:10:30Z")

</div>

You can still make it work, but to get hold of the non-interoperable Fortran type you’ll need to introduce a typeless “handle” object:

```fortran
module somemodule_wrap
  
  use, intrinsic :: iso_c_binding, only: &
      c_double, c_int, c_ptr, &
      c_f_pointer, c_loc
  use somemodule, only: sometype, frout2
  implicit none

contains

  type(c_ptr) function sometype_create(len) bind(c)
    integer(c_int), value :: len
    type(sometype), pointer :: p
    allocate(p)
    allocate(p%a(len))
    sometype_create = c_loc(p)
  end function

  type(c_ptr) function sometype_a(ptr, n) bind(c)
    type(c_ptr), intent(in), value :: ptr
    integer(c_int), intent(out) :: n
    type(sometype), pointer :: p => null()

    call c_f_pointer(ptr,p)
    if (allocated(p%a)) then
      n = size(p%a)
      sometype_a = c_loc(p%a)
    else
      sometype_a = c_null_ptr
    end if

  end function

  subroutine sometype_free(ptr) bind(c)
    type(c_ptr), value :: ptr
    type(sometype), pointer :: p => null()
    call c_f_pointer(ptr,p)
    if (allocated(p%a)) deallocate(p%a)
    deallocate(p)
  end subroutine

  subroutine frout2_wrap(ptr) bind(c)
    type(c_ptr), value :: ptr
    type(sometype), pointer :: p => null()
    call c_f_pointer(ptr,p)
    if (allocated(p%a)) then
      call frout2(p)
    end if
  end subroutine

end module

```

```c
// main.c
//
#include "somemodule_wrap.h"

int main(void) 
{
    void *h_sometype = sometype_create( 6 );

    int n;
    double *a;

    a = sometype_a(h_sometype, &n);
    for (int i = 0; i < n; i++) {
        a[i] = (double) i;
    }

    frout2_wrap(h_sometype);
    sometype_free(h_sometype);
    
    return 0;
}

```

Example build process and output:

```plaintext
ivan:~/fortran/somemodule$ make
gfortran -Wall -fcheck=all -std=f2018 -c somemodule.f90
gfortran -fc-prototypes -fsyntax-only somemodule_wrap.f90 > somemodule_wrap.h
gfortran -Wall -fcheck=all -std=f2018 -c somemodule_wrap.f90
gcc-10 -Wall -std=c11 -o main main.c somemodule_wrap.o somemodule.o -lgfortran
ivan:~/fortran/somemodule$ ./main
           1 6 6
   0.0000000000000000 1.0000000000000000 2.0000000000000000 3.0000000000000000 4.0000000000000000 5.0000000000000000  

```

`gfortran` is the only Fortran compiler I’m aware of that supports [generation of the corresponding C prototypes](https://fortran-lang.discourse.group/t/compilers-supporting-generation-of-c-function-prototypes/2688).

* * *

Edit: here are the build files (both CMake and a custom Makefile) in case anyway is interested:

```plaintext
ivan:~/fortran/somemodule$ tree
.
├── CMakeLists.txt
├── Makefile
├── main.c
├── somemodule.f90
└── somemodule_wrap.f90

0 directories, 5 files

```

> **CMakeLists.txt**
>
> ```plaintext
> cmake_minimum_required(VERSION 3.12.0)
> 
> project(someproject VERSION 0.1.0 LANGUAGES C Fortran)
> 
> add_library(
> somemodule
> somemodule.f90
> somemodule_wrap.f90
> )
> 
> add_custom_command(
> OUTPUT somemodule_wrap.h
> COMMAND gfortran -fc-prototypes -fsyntax-only ${CMAKE_CURRENT_SOURCE_DIR}/somemodule_wrap.f90 > ${CMAKE_CURRENT_SOURCE_DIR}/somemodule_wrap.h
> DEPENDS somemodule_wrap.f90
> )
> 
> add_executable(main main.c somemodule_wrap.h)
> target_link_libraries(main somemodule)
> 
> ```

> **Makefile**
>
> ```plaintext
> FC=gfortran
> CC=gcc-10
> 
> FCFLAGS=-Wall -fcheck=all -std=f2018
> CFLAGS=-Wall -std=c11
> 
> LDFLAGS=-lgfortran
> 
> .phony: all clean
> 
> all: main
> 
> main: main.c somemodule_wrap.o somemodule.o
> $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
> 
> main.c: somemodule_wrap.h
> 
> somemodule_wrap.h: somemodule_wrap.f90
> gfortran -fc-prototypes -fsyntax-only $< > $@
> 
> somemodule_wrap.f90: somemodule.mod
> 
> somemodule_wrap.o somemodule_wrap.mod: somemodule_wrap.f90 somemodule.mod
> $(FC) $(FCFLAGS) -c $<
> 
> somemodule.o somemodule.mod: somemodule.f90
> $(FC) $(FCFLAGS) -c $<
> 
> clean:
> rm -rf *.o *.mod somemodule_wrap.h main
> 
> ```

---

_[View the full topic](https://fortran-lang.discourse.group/t/allocate-interoperability-and-c-descriptors/5088)._
