- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I am trying to expose some Fortran subroutines in a DLL.
I didn't write the Fortran code, and I'm having some difficulties creating the DLL.
The Fortran code is something like this (simplified):
! ===========================================================================
! Some declarations, initialisations etc
contains
subroutine Initialisation
!DEC$ ATTRIBUTES DLLEXPORT::Initialisation
!Do some stuff here
end subroutine Initialisation
! ===========================================================================
I keep getting this error:
DEC$ ATTRIBUTES DLLEXPORT attribute can not be assigned to an internal procedure.
I understand that this is because the subroutine is define underneath the "contains" keyword.
I've tried removing this but then I get a load more errors, so i'd rather not go down that route.
Is there an easy was of getting round this problem? I have googled for the error message but can't find a solution
Thanks
Dom
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Not necessarily.
You could turn the program and the internal routine into a module. Something along these lines:
module myprogram
... declarations of the variables in the current main program
contains
subroutine the_old_program( only_init )
logical :: only_init ! Use this to only initialise the variables that are needed in the internal routine
....
if ( only_init ) then
....
endif
...
end subroutine the_old_program
subroutine initialisation( .... )
! The current internal routine
...
end subroutine initialisation
end module myprogram
To use the_old_program subroutine in the testing context, use:
program test_myprogram
use test_myprogram
call the_old_program( .false. )
end program test_myprogram
Well, just a sketch.
Regards,
Arjen
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You say it is an internal routine, but from the code it is not clear whether it is an internal routine (so belonging to a function or a subroutine) or a module procedure. If it is indeed an internal routine it can only be invoked from within the containing function or subroutine - whether it is all part of a DLL or a static library. If it is a module procedure, then it can be invoked from the outside, but it has to have the public attribute (which is the default).
Since it is not entirely clear what you have exactly, here are two fragments to show both situations:
integer function myfunc( x ) integer, intent(in) :: x call my_helper( x, myfunc ) ... contains subroutine my_helper( x, y ) ! Inside the function, so invisible from the outside! integer :: x, y ... do something useful ... end subroutine my_helper end function myfunc
And the other one is:
module mymodule private :: my_helper contains integer function myfunc( x ) call my_helper( x, myfunc ) ... end function myfunc ... subroutine my_helper( x, y ) ! Outside the function, but inside the module - note the private attribute integer :: x, y ... do something useful ... end subroutine my_helper end module mymodule
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi, thanks for the reply
The subroutine doesn't belong to a function or a subroutine, or a module. It belongs to the program (I really am unfamiliar with Fortran, and as I say, it's not my code).
The code is something like this (in fact, you can copy this dummy code exactly to get the error message I describe):
program MY_PROGRAM
! ===========================================================================
! ===========================================================================
implicit none
! Lots of declarations here
! ===========================================================================
! ===========================================================================
call Initialisation
!! ===========================================================================
!! ===========================================================================
contains
! ===========================================================================
! ===========================================================================
subroutine Initialisation
!DEC$ ATTRIBUTES DLLEXPORT::Initialisation
end subroutine Initialisation
end program MY_PROGRAM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Right, that is a situation I forgot about :).
Since it is part of a program, it is meant to be used in conjunction with that program. That leads me to the question why this particular routine should be used outside it? Do you want to turn the program as such into a library for use in another program or is it simply this routine? Note that whatever your answer, you will have to adjust the code to a certain extent.
Regards,
Arjen
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Arjen,
It is simply this routine that I wish to call externally (actually, there are a few more routines that I wish to use, but in the same manner).
I'm not interested in the program (the program is just really a testbed which calls the subroutines in the same way that I wish to call them externally).
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You can't do this. An internal procedure requires context of its host to be passed and that's not available if you try to make it "external".
If the internal procedures don't need to inherit variables from the main program, move them to a module and USE the module from the main program. Then you can export them.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Steve,
Thanks for your reply
The internal procedures DO need to use variables that are declared in the main program.
I guess this is the problem I face.
I had previously been using the Silverfrost Fortran compiler to make a DLL, and that seemed to let me do what I wanted (expose internal procedures which had everything in scope when I ran them externally).
But then I ran into compile issues (because the Fortran developer who writes the code uses the Intel compiler, so I switched to Intel also).
Now I have these DLL issues. I don't really know what the best solution is to this. Probably get the Fortran developer to fix the Silverfrost compile issues and proceed from there.
Thanks
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Not necessarily.
You could turn the program and the internal routine into a module. Something along these lines:
module myprogram
... declarations of the variables in the current main program
contains
subroutine the_old_program( only_init )
logical :: only_init ! Use this to only initialise the variables that are needed in the internal routine
....
if ( only_init ) then
....
endif
...
end subroutine the_old_program
subroutine initialisation( .... )
! The current internal routine
...
end subroutine initialisation
end module myprogram
To use the_old_program subroutine in the testing context, use:
program test_myprogram
use test_myprogram
call the_old_program( .false. )
end program test_myprogram
Well, just a sketch.
Regards,
Arjen
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks Arjen, that worked! :-)
The DLL has been created, and dependency walker shows the exported functions in the function list.
So my current problem has been solved.
Thanks very much
Dom
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page