# C interoperability with assumed-shape arrays

**URL:** <https://fortran-lang.discourse.group/t/c-interoperability-with-assumed-shape-arrays/6266>\
**Category:** Uncategorized\
**Created:** [August 3, 2023, 1:55pm UTC](https://fortran-lang.discourse.group/t/c-interoperability-with-assumed-shape-arrays/6266 "2023-08-03T13:55:41Z")\
**Posts on this page:** 1\
**Showing post:** 12

<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:** [August 3, 2023, 10:39pm UTC](https://fortran-lang.discourse.group/t/c-interoperability-with-assumed-shape-arrays/6266/12 "2023-08-03T22:39:52Z")

</div>

> [@FortranFan](#):
>
> Take a look at the example I provide. The code in Fortran is compact and highly functional and thus at a **higher** level of abstraction. Whereas it is at a **low** level in C. This is exactly as one would want. Subliminally, it should inform and influence scientists and technologists and engineers to move more of their coding to a higher level language of Fortran offering efficient computation with functional offering of containers of their data rather than raw pointers and user-defined structs to work with them, like in C.

If you use C++17 (or higher), you can have high level code just like in Fortran.

```cpp
#include <array>
#include <numeric>

#include "Fcpp.h" // <-- C++ descriptor adaptor

// Fortran routine
extern "C" void sub(CFI_cdesc_t *);

int main(void)
{
    using namespace Fcpp;

    std::array<int,5> x;
    std::iota(x.begin(),x.end(),42); // or std::ranges::iota(x,42) in C++23

    sub(desc(x)); /* Create adaptor on the fly */

    return 0;
}

```

```txt
~/tmp$ gfortran-13 -c m.f90 # module providing routine sub
~/tmp$ g++-13 -Wall -std=c++17 wrapper.cpp m.o -lgfortran
~/tmp$ ./a.out
 In Fortran sub: size(x) = 5
          42 43 44 45 46

```

How does it work? Well you create an adaptor using a templated class; all the ugly work is hidden in the constructor. Click on the little arrow (triangle) for a look at the internals:

> **Fcpp - Adaptor between C++ and Fortran**
>
> ```auto
> #include <cassert>
> #include <array>
> #include <vector>
> 
> #include "ISO_Fortran_binding.h"
> 
> namespace Fcpp {
> 
> namespace {
> 
> // Type converters
> template<typename T>
> constexpr CFI_type_t type(){ return CFI_type_other; };
> template<>
> constexpr CFI_type_t type<float>(){ return CFI_type_float; } 
> template<>
> constexpr CFI_type_t type<double>(){ return CFI_type_double; } 
> template<>
> constexpr CFI_type_t type<int>(){ return CFI_type_int; } 
> 
> }
> 
> // Descriptor Adaptor - provides Fortran descriptor of a C++ entity
> template<typename T>
> class desc {
> public:
> 
> desc(T* ptr, int n0) {
> 
> CFI_index_t extents[] = { 
> static_cast<CFI_index_t>(n0)};
> 
> [[maybe_unused]] int status = CFI_establish(
> this->get(),
> ptr,
> CFI_attribute_other,
> type<T>(),
> sizeof(T),
> 1,
> extents
> );
> 
> assert(status == CFI_SUCCESS);
> 
> }
> 
> // Constructor from std::vector
> desc(std::vector<T> &buffer) : desc(buffer.data(),buffer.size()) {}
> 
> // Constructor from std::array
> template<std::size_t N>
> desc(std::array<T,N> &buffer) : desc(buffer.data(),N) {}
> 
> // Return pointer to the underlying descriptor
> constexpr auto get() const { 
> return (CFI_cdesc_t *) &desc_; 
> }
> 
> // Implicit cast to C-descriptor pointer
> operator CFI_cdesc_t* () { return this->get(); }
> 
> private:
> CFI_CDESC_T(1) desc_;
> };
> 
> } // namespace Fcpp
> 
> ```

---

_[View the full topic](https://fortran-lang.discourse.group/t/c-interoperability-with-assumed-shape-arrays/6266)._
