I've got a Fortran-Dll which will be used by all kind of other programs (e.g. Excel-VBA, Python, C/C++ programs).
The Fortran-Dll is stateless (i.e. no static-variables, SAVE or DATA). All data is either on the stack or dynamically allocated, thus the dll can be used parallel without restrictions. (OpenMP is NOT used since it reduces the parallelization to OpenMP-threads only).
Let's assume there is an exported function CALCULATE from the dll. On each call CALCULATE allocates a large user-defined structure, initializes it, makes some calculations and returns the result AND deallocates the user-defined structure again.
Since the initialization of the user-defined structure is quite complex, I would like to re-use it for multiple calls to CALCULATE. Below is a sketch of my current approach to this (returning the address of the user-defined structure to the caller)
My question is: Is there any other/better or even standardized way to export Fortran allocated data?
integer(c_intptr_t) function CREATE_DATA (arg_1, ... , arg_n) !DEC$ ATTRIBUTES DLLEXPORT::CREATE_DATA use, intrinsic :: iso_c_binding implicit none type(large_udt),pointer :: data allocate(data) ! use arg_1,...,arg_n to initialize data ! call setup(data, arg_1,...,arg_n)
CREATE_DATA = LOC(data) end function CREATE_DATA subroutine DESTROY_DATA (handle) !DEC$ ATTRIBUTES DLLEXPORT::DESTROY_DATA use, intrinsic :: iso_c_binding implicit none integer(c_intptr_t), intent(in) :: handle type(type_udt),target :: data type(type_udt),pointer :: data_ptr pointer(handle,data) data_ptr => data deallocate(data_ptr) end subroutine DESTROY_DATA
function CALCULATE (handle,args...) !DEC$ ATTRIBUTES DLLEXPORT::CALCULATE use, intrinsic :: iso_c_binding implicit none integer(c_intptr_t), intent(in) :: handle
type(type_udt),target :: data type(type_udt),pointer :: data_ptr pointer(handle,data)
! do calculation using data and args and return result
end function CALCULATE
Not sure what you mean by a better way, but in terms of "other" you can look into the enhanced interoperability with C features in standard Fortran in situations where the other programs you work with (using C++, etc.) do involve a companion C processor. You may know of Intel's documentation of the C interop facilities: https://software.intel.com/en-us/node/678422 e.g., simulation example in this link.
I was concerned about th LOC function which AFAIK is not standard. But I just found out about C_LOC and C_F_POINTER which give the guarantees I need (especially for non-interoperable types).