![forums.silverfrost.com Forum Index](templates/subSilver/images/logo_phpBB.gif) |
forums.silverfrost.com Welcome to the Silverfrost forums
|
View previous topic :: View next topic |
Author |
Message |
mecej4
Joined: 31 Oct 2006 Posts: 1886
|
Posted: Thu Mar 16, 2017 12:53 pm Post subject: How to link code compiled by FTN95-64 with third-party DLLs |
|
|
I claimed in another thread that one could use routines contained in third-party DLLs from code compiled by FTN95-64. John Campbell asked me by private mail to provide a recipe, and I am responding here so that other readers interested in the topic can also see.
I give a how-to description using a very simple example. More complicated cases may respond to the same procedure, but you may run into difficulties if the DLL routines do I/O or the DLL was built with a different calling convention than the standard Windows-64 ABI (CDECL, first four arguments in RCX, RDX, R8 and R9, the rest on the stack, etc.), or there are descriptors to be passed, optional arguments are passed, there is global shared data, etc.
Note also that it may be next to impossible to debug the mixed-pedigree program that you produce. It is best to test and debug the DLL routine in some native environment first.
Here is the example. A driver main program compiled with FTN95 calls a routine compiled with Gfortran which returns a vector that contains the elements of an input vector but in reverse order.
The code for the DLL, file rvec.f90:
Code: | subroutine reverse_vec(x,y,n)
implicit none
integer, intent(in) :: n
real, dimension(n), intent(in) :: x
real, dimension(n), intent(out) :: y
integer :: i
do i=1,n
y(n+1-i) = x(i)
end do
return
end subroutine reverse_vec |
We compile this into a DLL using Gfortran 6.2-64bit:
Code: | gfortran -shared -o rvec.dll rvec.f90
|
The driver program, tvec.f90:
Code: | program tvec
implicit none
C_EXTERNAL reverse_vec 'reverse_vec_'
real :: x(4) = [1,2,3,4], y(4)
write(*,*)x
call reverse_vec(x,y,4)
write(*,*)y
end program tvec |
Compile and link the driver using FTN95:
Code: | ftn95 tvec.f90 /64
slink64 tvec.obj rvec.dll /file:tvec |
You may note that the DLL is quite big. That is because it has a fixed overhead of having to contain the parts of the Gfortran runtime that the DLL routine needs.
Also note that the DLL does not have to be produced from Fortran code or be generated using Gfortran.
Last edited by mecej4 on Sat Feb 16, 2019 3:16 pm; edited 1 time in total |
|
Back to top |
|
![](templates/subSilver/images/spacer.gif) |
John-Silver
![](http://i.postimg.cc/K8HMTnXq/Bart-Unrivalled-Native-Plotting256.jpg)
Joined: 30 Jul 2013 Posts: 1520 Location: Aerospace Valley
|
Posted: Fri Mar 17, 2017 6:55 pm Post subject: |
|
|
so basically it's just a question of declaring the dll outine via C:EXTERNAL in the calling program ?
Of course the called DLL must be 64 bit also I assume.
There's some documentation about using for calling a C++ DLL here .....
http://silverfrost.com/ftn95-help/mixlan/callingc_c__fromftn95.aspx |
|
Back to top |
|
![](templates/subSilver/images/spacer.gif) |
mecej4
Joined: 31 Oct 2006 Posts: 1886
|
Posted: Fri Mar 17, 2017 8:17 pm Post subject: Re: |
|
|
John-Silver wrote: | so basically it's just a question of declaring the dll outine via C:EXTERNAL in the calling program ? |
Even that is unnecessary if the external program uses the same name decoration that FTN95 does (all uppercase, no underscore appended). One should also note that "C" does not really mean that the external code has to be written in C, but that it must behave in the same way as C code compiled with a certain Fortran-compatible C compiler.
Quote: | Of course the called DLL must be 64 bit also I assume. |
Of course. |
|
Back to top |
|
![](templates/subSilver/images/spacer.gif) |
JohnCampbell
Joined: 16 Feb 2006 Posts: 2554 Location: Sydney
|
Posted: Mon Mar 20, 2017 1:45 am Post subject: |
|
|
mecej4,
Thanks very much for your example. I have it working.
Now to experiment with what can be placed in the .dll and how to transfer information between the FTN95 memory and the .dll.
Functionality like multi-threading and some write reporting could be good.
Must this .dll be self sufficient or can it call FTN95 supplied routines ?
One thing I can't do is get an equivalent to Slink64's /map:tvec for the list of symbols in the .dll. When expanding the capabilities of "rcec.dll", it would be good to have a list of:
# what symbols are available to tvec.f90 from the .dll,
# what symbols are included in the rvec.dll build (library routines) and
# what other .dll's are required by rvec.dll
John |
|
Back to top |
|
![](templates/subSilver/images/spacer.gif) |
mecej4
Joined: 31 Oct 2006 Posts: 1886
|
Posted: Mon Mar 20, 2017 3:26 am Post subject: |
|
|
It is easiest if you restrict yourself to passing data as routine arguments. Sharing global variables between a DLL and an EXE is complicated and errorprone. If more than one EXE may be running that depends on a DLL, you have to arrange for locks, etc. on those variables.
You can use the MS DUMPBIN utility or the GNU utility NM to display the symbols exported by a DLL. You can use Dependency Walker to list the other DLLs that are used by a specific DLL. |
|
Back to top |
|
![](templates/subSilver/images/spacer.gif) |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|