Allocate interoperability and C descriptors

I’ve been confused in the past with wrappers (like in this StackOverflow thread). Typically you find examples of wrapping non-interoperable C/C++ objects in Fortran rather than the other way round. I guess not that many C/C++ developers appreciate the features of modern Fortran.

Btw, in case you are willing to use C++, the C API can be wrapped in a C++ class which has the benefit of automatic lifetime management (RAII) and other C++ goodies like std::span and the STL:

#include <numeric>
#include <span>

#include "somemodule_wrap.h"

class Sometype {
public:

    // Constructor
    Sometype(int n) : ptr{ sometype_create(n) } {}

    // Destructor
    ~Sometype() { sometype_free(ptr); }

    // Access array member `a`
    std::span<double> a() const {
        int n; double *a;
        a = static_cast<double *>( sometype_a(ptr,&n) );
        return { a, (size_t) n };
    }

    // Retrieve raw pointer to underlying object
    void *get() const { return ptr; }

private:
    void *ptr{nullptr};
};

void frout(const Sometype& x) {
    frout2_wrap( x.get() );
}

The usage becomes simpler than in C and you get to use STL algorithms with the std::span

int main(void) 
{
    Sometype x{6};
    
    auto a = x.a();    // a is a view (memory owned by x)

    // Fill with increasing numbers
    std::iota(a.begin(),a.end(),0.0);
    
    frout(x);

    return 0;
}
1 Like