Created
September 27, 2022 15:41
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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