Skip to content

Instantly share code, notes, and snippets.

@ivan-pi
Created September 27, 2022 15:41
Show Gist options
  • Save ivan-pi/614584e3f2b7009a8ceddfbe5aaae91e to your computer and use it in GitHub Desktop.
Save ivan-pi/614584e3f2b7009a8ceddfbe5aaae91e to your computer and use it in GitHub Desktop.
Example of using C descriptors to call a routine implemented in Fortran
module interop
use, intrinsic :: iso_c_binding, only: c_int
implicit none
contains
subroutine fillint(arr) bind(c)
integer(c_int), intent(inout) :: arr(:)
integer :: i
arr = [(i**2,i=1,size(arr))]
end subroutine
end module
// For GCC compile using
// gfortran -Wall -c interop.f90
// g++ -Wall main.cpp interop.o -lgfortran
#include <vector>
#include <iostream>
#include <array>
#include <initializer_list>
#include <numeric>
#include <ISO_Fortran_binding.h>
/**
* Fortran routine prototypes
*/
extern "C" {
void fillint(CFI_cdesc_t *res);
}
int main(int argc, char const *argv[])
{
const int N = 5;
std::vector<int> myresult(N);
CFI_CDESC_T(1) res_desc; /* Rank-1 array descriptor */
// The C descriptor is an opaque struct that stores
// information about a Fortran objects which have
// no proper equivalent in C. Such structs can be
// used as dummy arguments in inter-language calls.
// The descriptor can only be modified by functions provided
// in the header "ISO_Fortran_binding.h". These functions
// expect a pointer to the array descriptor.
auto res = reinterpret_cast<CFI_cdesc_t *>(&res_desc);
// First we establish a local array of extents
// In this case we are wrapping a std::vector, which
// can be seen as a 1-dimensional array.
CFI_index_t res_extents[1] = { N };
// Now we establish the C-descriptor.
// In this case `res` will be a rank-1 array
// of type double referring to the data
// in the std::vector `myresult`.
int err = CFI_establish(
desc.get(), /* pointer to the descriptor */
myresult.data(), /* pointer to the data */
CFI_attribute_other, /* attribute */
CFI_type_double, /* type of */
sizeof(double), /* size of element */
1, /* rank */
res_extents); /* array extents */
// In case something went wrong, a non-zero
// value is returned, which can be used for
// error-checking
if (err != CFI_SUCCESS)
return 1;
// Now we have a complete descriptor which
// can be passed to a Fortran routine.
fillint(desc);
for(auto v : myresult) {
std::cout << v << ' ';
}
std::cout << '\n';
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment