- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I am very new to Fortran but I have been tasked with an interesting problem.
For the past months I have been working on splitting a large Fortran application into 2 pieces and I am now looking at passing data between the two halves (call them App1 and App2)
Much of the data is in the form of arrays and I have decided to use pointers to get this data across quickly ... this seems to have worked well for fixed length arrays... e.g....
In App1....
INTEGER MYARRAY(10)
INTEGER MYARRAYLOC
MYARRAYLOC = LOC(MYARRAY)
Pass MYARRAYLOC to App2 as an argument
In App2....
INTEGER MYARRAY2(10)
POINTER (PTR_MA, MYARRAY2)
PTR_MA = MYARRAYLOC
However, if we have....
INTEGER, ALLOCATABLE::MYARRAY( : , : )
INTEGER MYARRAYLOC
MYARRAYLOC = LOC(MYARRAY)
Pass MYARRAYLOC to App2 as an argument
In App2....
INTEGER, ALLOCATABLE::MYARRAY2( : , : )
POINTER (PTR_MA, MYARRAY2)
PTR_MA = MYARRAYLOC
We get error #7230: An integer pointee cannot have the F90 ALLOCATABLE attribute.
Is what I am trying to do even possible? Is there a better\different way to do it?
Thank you.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You are using an extension often referred to as "Cray pointers". This is not the Fortran standard pointer syntax. However, I don't quite understand what you are trying to do. You don't have two separate applications, just different sets of procedures in one application. Why can't you just pass the array directly?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Steve,
Thanks for your reply.
Yes ... this is the issue ... I want to pass the array from one fortran DLL to another. Furthermore, each DLL has a C wrapper around it ... so passing the array directly "as is" isn't going to work.
However .... I've come up with the solution .... I perhaps over thought it....
There are many arrays and variables that need passing across the DLL boundary and I've wrapped them all up in a Type ... I simply need to pass the address of the instance of the Type created in App1 across to App2 and it comes through nicely. The Type can contain fixed arrays as well as dynamic arrays.
Thanks for the mention of the "Cray pointers" .... this maybe explains why they don't work as well as I'd hoped .... they don't seem to want to use a Target that is housed as a global in an INC file ... so I've been having to work round that which creates a performance hit.
I have seen what I assume is a more modern Pointer syntax online so I will look into using that instead.
Thanks again for your help.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Modern Fortran has features that can help you, but I don't understand why you can't just pass the array to the C wrapper, which accepts it as a pointer to something and then passes that to the Fortran code. If nothing else, you can use the C interoperability features, pass C_LOC(array) (which is a C pointer) and that can be passed to the other DLL which calls C_F_POINTER (from intrinsic module ISO_C_BINDING) to "convert" the C pointer (type C_PTR) to a Fortran POINTER to whatever you want, with the bounds you specify.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Yes .... I can pass the pointer no problem .... the issue seems to be resolving the pointer to a target in App2 .... it doesn't seem to be happy with Allocatable arrays .... works fine with fixed arrays.
Like I say ... I do have a solution ... to wrap everything up (variables, fixed and dynamic arrays, everything) in a Type and pass the pointer of the instance of that... works fine.
I'm going to play about a bit more with Pointers.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@MarkEH ,
If you have not tried this already, you may find it helpful to put together minimal working examples toward your specific needs and post them here in case you have any pending questions or issues.
Note with Fortran DLLs on Windows, you don't necessarily need C wrappers though you can include them if there is a need to consume the Fortran code from other platforms such as other C/C++ applications including those from 3rd party, Excel VBA, Microsoft .NET etc.
On the other hand, you can retain pure Fortran APIs also that can be used by other Fortran DLLs and Fortran main programs.
Toward a minimal working example, if you are unclear how to start with modern Fortran given your comment you're new to Fortran, you can consider the following.
Say your first DLL works with a rank-1 array of integer type, of course it can be any type in actual code, this is just an illustration. You can include Fortran APIs to update the "data" toward such an array and to access the data with a `pointer` type in order to avoid *copying* the data in caller code from another DLL or EXE, say like so:
module dll_one_m
private
integer, protected, allocatable, target, save :: dat_dll_one(:)
! Public entities
public :: update_dat_dll_one, setptr_dat_dll_one
contains
subroutine update_dat_dll_one()
dat_dll_one = [ 1, 3, 5 ]
end subroutine
subroutine setptr_dat_dll_one( pdat )
integer, pointer, intent(inout) :: pdat(:)
pdat => dat_dll_one
end subroutine
end module
And you may use either Visual Studio or other IDE app or perhaps even the command line to package the above code into a DLL. Note the DEF file per Microsoft that I recommend:
C:\Temp>ifort /c /standard-semantics dll_one.f90
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.6.0 Build 20220226_000000
Copyright (C) 1985-2022 Intel Corporation. All rights reserved.
C:\Temp>link dll_one.obj /def:dll_one.def /out:dll_one.dll
Microsoft (R) Incremental Linker Version 14.32.31329.0
Copyright (C) Microsoft Corporation. All rights reserved.
Creating library dll_one.lib and object dll_one.exp
* module definition file: dll_one.def
LIBRARY dll_one
EXPORTS
DLL_ONE_M_mp_UPDATE_DAT_DLL_ONE @1
DLL_ONE_M_mp_SETPTR_DAT_DLL_ONE @2
Now say your second DLL works with a rank-1 array of real type and it consumes the integer array from the first DLL and similar to first DLL, it exposes two APIs, one to compute this DLL "data" and the other to make the data accessible:
module dll_two_m
use dll_one_m, only : setptr_dat_dll_one
private
real, protected, allocatable, target, save :: dat_dll_two(:)
! Public entities
public :: update_dat_dll_two, setptr_dat_dll_two
contains
subroutine update_dat_dll_two()
integer, pointer :: pdat_dll_one(:)
call setptr_dat_dll_one( pdat_dll_one )
dat_dll_two = [( 0.0, integer :: i = 1, 6 )]
dat_dll_two(pdat_dll_one) = real( pdat_dll_one )
pdat_dll_one => null()
end subroutine
subroutine setptr_dat_dll_two( pdat )
real, pointer, intent(inout) :: pdat(:)
pdat => dat_dll_two
end subroutine
end module
And the same steps toward packaging:
C:\Temp>ifort /c /standard-semantics dll_two.f90
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.6.0 Build 20220226_000000
Copyright (C) 1985-2022 Intel Corporation. All rights reserved.
C:\Temp>link dll_two.obj dll_one.lib /def:dll_two.def /out:dll_two.dll
Microsoft (R) Incremental Linker Version 14.32.31329.0
Copyright (C) Microsoft Corporation. All rights reserved.
Creating library dll_two.lib and object dll_two.exp
* Similar module-definition file: dll_two.def
LIBRARY dll_two
EXPORTS
DLL_TWO_M_mp_UPDATE_DAT_DLL_TWO @1
DLL_TWO_M_mp_SETPTR_DAT_DLL_TWO @2
Now you can have a Fortran calling app that consumes both the DLL and the data therein:
use dll_one_m
use dll_two_m
integer, pointer :: pdat_dll_one(:)
real, pointer :: pdat_dll_two(:)
call update_dat_dll_one()
call setptr_dat_dll_one( pdat_dll_one )
print *, "dat_dll_one = ", pdat_dll_one
call update_dat_dll_two()
call setptr_dat_dll_two( pdat_dll_two )
print *, "dat_dll_two = ", pdat_dll_two
pdat_dll_one => null()
pdat_dll_two => null()
end
C:\Temp>ifort /c /standard-semantics p.f90
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.6.0 Build 20220226_000000
Copyright (C) 1985-2022 Intel Corporation. All rights reserved.
C:\Temp>link p.obj dll_one.lib dll_two.lib /subsystem:console /out:p.exe
Microsoft (R) Incremental Linker Version 14.32.31329.0
Copyright (C) Microsoft Corporation. All rights reserved.
C:\Temp>p.exe
dat_dll_one = 1 3 5
dat_dll_two = 1.000000 0.000000 3.000000 0.000000
5.000000 0.000000
As I mentioned above, this is just an illustration. You can adapt this toward your needs or put together something else and post here to get your specific questions answered.
And if you do indeed need to work with C wrappers and C callers of Fortran procedures and the data, you can look into interoperability features with C in modern Fortran.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@MarkEH ,
By the way, since you're new to Fortran and may have questions generally about Fortran, particularly those with the current standard - Fortran 2018 - that is supported by Intel one IFORT compiler. This may be of interest because Fortran 2018 offers many facilities beyond the style you might see in code from the period starting 1950s thru' early 1990s (e.g., with Cray "pointers" above). If so, you may want to also inquire at the Fortran Discourse and review material available at Fortran-lang.org:
https://fortran-lang.discourse.group/

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page