-
Notifications
You must be signed in to change notification settings - Fork 184
Fortran/C++ compatibility library #325
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
As a small further example, I have added an attribute parameter to the namespace cfi {
typedef CFI_attribute_t attribute_t;
enum attribute {
allocatable = CFI_attribute_allocatable,
pointer = CFI_attribute_pointer,
other = CFI_attribute_other
};
}
template <typename T, cfi::attribute_t attribute = cfi::attribute::other>
struct FortranArray {
// ...
// Constructor
FortranArray(const CFI_cdesc_t *obj) :
base_addr(obj->base_addr), dim(obj->dim) {
// Make sure true attribute and declared attribute match
assert(obj->attribute == attribute);
}
}
using cfi::attribute::allocatable;
void process_allocatable_array(const CFI_cdesc_t *array) {
FortranArray<double, allocatable> a(array); // If attributes don't match, assertion fails.
} E.g. trying to call
The error message could be improved with some preprocessor syntax. Similar run-time checks of the shadow C++ class could be done for the rank and type of the array. Type-checking can be done like this:
|
So I just added the following iterator code: struct Iterator
{
using iterator_category = std::forward_iterator_tag;
using difference_type = std::ptrdiff_t;
using value_type = real_t;
using pointer = real_t *;
using reference = real_t &;
Iterator(pointer ptr) : m_ptr(ptr) {}
reference operator*() const { return *m_ptr; }
pointer operator->() { return m_ptr; }
Iterator& operator++() { m_ptr++; return *this; }
Iterator operator++(int) { Iterator tmp = *this; ++(*this); return tmp; }
friend bool operator== (const Iterator& a, const Iterator& b) { return a.m_ptr == b.m_ptr; };
friend bool operator!= (const Iterator& a, const Iterator& b) { return a.m_ptr != b.m_ptr; };
private:
pointer m_ptr;
};
Iterator begin() { return (address(0)); }
Iterator end() { return (address(this->size())); }
inline real_t *address(const size_t i) {
real_t *val = const_cast<real_t *>(
static_cast<const real_t*>(this->base_addr));
return &val[i];
} into the FortranArray class (no guarantees this is legitimate C++...; I just followed some tutorial). A subroutine to multiply by a scalar can be written as: void multiply_by_two(CFI_cdesc_t *array) {
Vector f_array(array);
for (auto &element: f_array) {
element *= 2.0;
}
} For the demo program:
I get the output:
|
I agree completely. This was my thinking when you posted on the Discourse; this will definitely be useful to have in a library. I'm tempted to say it should be its own library separate to stdlib. |
I'm interested in whether this would also allow straightforward usage of the oneAPI parallel STL directly on the memory of Fortran objects. |
I just seized GTC 2021 as an opportunity to ask @brycelelbach about using C++ standard parallel algorithms on Fortran array objects using the new NVC++ and NVFORTRAN compilers. His answer:
Great way to get the best of both worlds. |
With the introduction of Fortran 2018 enhancements to interoperability with C it is possible to write C (and C++) code which interoperates with
To handle such objects the standard introduced the concept of C descriptors which are defined in the header
"ISO_Fortran_binding.h"
header provided by the Fortran processor.While very powerful, using these low-level tools to access Fortran objects feels clunky and error-prone. It would be nice to provide some higher level tools in the form of templated C++ wrapper classes. A similar concept is followed by the popular and fast-growing Rcpp library for R and C++ integration.
Here is a minimal example of such a wrapper class (kudos to @LKedward for helping me overcome a problem with C descriptor lifetimes in the Discourse thread) :
Given the popularity of C++ and it's strong presence in scientific computing, I think these tools would go a long way to increase adoption of Fortran as a viable co-language. Ideally, one would implement an STL-compatible container interface, allowing to use C++ algorithms directly on Fortran arrays.
A few questions:
stdlib
?std::sin(array(i))
or a Fortran versionfortran::sin(array(i))
)The text was updated successfully, but these errors were encountered: