- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello All,
I've been searching on the forum intermittently for about a month now, and
either my problem isn't represented, or I'm not looking in the right places.
Nonetheless, here it is: I have created a Visual Studio / Fortran program that
uses a Visual Studio GUI to call the Fortran DLL. Everything seems to work fine
in that regard. My problem is that, within the Fortran DLL, I am attempting to
pass a subroutine as an argument into the November 2003 version of LLNL's
DLSODA subroutine (I'm sure it doesn't matter what the destination is, but just
in case). Here's the call that occurs within the DLL:
CALL dlsoda(fex_fun,neq,f,xin,xout,itol,rtol,atol, &
itask,istate,iopt,rwork,lrw,iwork,liw,jac,jt)
The subroutine is "fex_fun", and is declared elsewhere as:
SUBROUTINE fex_fun(NEQ, X, F, FPRIME)
How should I declare (and where) this fex_fun subroutine so that I can call it
as an argument in another subroutine? I've tried using the EXTERNAL declaration,
but I must not be using it correctly. Any help would be appreciated.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
external fex_fun
or it may have a complete explicit interface nested within the interface for dlsoda. If that's the case, then you'll need to write a compatible explicit interface for fex_fun.
Is this dlsoda Fortran code that you also compiled with the Intel compiler, or is it in some other library or DLL? If it isn't Fortran source, you will need to know dlsoda's calling convention.
What error messages are you seeing?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Steve. Thanks for the quick reply. The DLSODA routine is
part of the much larger ODEPACK.F file put out by LLNL. Though, I am attempting
to only use the part concerned with DLSODA, since the whole file is more than
27,000 lines long. I am compiling the DLSODA routine by including it in a
separate file and module, like this:
!dlsoda.f90
MODULE DLSODA_MOD
public :: dlsoda
contains
subroutine dlsoda(FEX_FUN,...)
external FEX_FUN
...
end subroutine dlsoda
END MODULE DLSODA_MOD
The FEX_FUN subroutine is placed in the same file as the subroutine that calls
DLSODA, like this:
!main.f90
MODULE main_mod
public :: caller_sub
contains
subroutine
caller_sub(...)
use
DLSODA_MOD
...
CALL
dlsoda(FEX_FUN,...)
...
end subroutine
caller_sub
!!**************************!!
subroutine
FEX_FUN(...)
...
end subroutine
FEX_FUN
END MODULE main_mod
I attempted to simply put "external FEX_FUN"
in the declarations of the caller_sub subroutine, but I get this error:
MAIN.obj : error LNK2019: unresolved external symbol _FEX_FUN referenced in
function _MAIN_MOD_mp_CALLER_SUB
Let me know if any more information is required.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks again,
Jason
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
call foo(mysub)
The compiler needs to figure out what "mysub" is - it could be a variable or it could be a routine. If no other information is available, it's a variable. Simple. If you give mysub a type, it could still be a variable or a function. Somehow the compiler has to know it's a routine.
The F77 way to do this, which was the only way in F77, was to add an EXTERNAL declaration for mysub. This informs the compiler that it is an external procedure, or "confirms" that mysub is a BLOCK DATA subprogram which is part of the application. Either way, this gives the compiler enough information to generate an external reference to mysub (normally _MYSUB on IA-32) and pass that address as the argument.
In F90, we have explicit interfaces which can be provided several ways. Any of them, if visible to the caller, will let the compiler know that mysub is a routine and not a variable. When mysub is a module procedure the compiler also knows how to decorate the external name relating to the module, for example, _MODNAME_mp_MYSUB, since you could theoretically have two or more routines named MYSUB in the application (just can't use the name if two definitions are visible at the same time.)
So in your program, the compiler already knew that fex_fun was a function and how to find it - nothing else was needed. In fact, adding EXTERNAL hid your module procedure ext_fun and told the compiler that you wanted some other external procedure, which is what produced the reference to _EXT_FUN.
Note that while it is standard-conforming to pass a module procedure as an actual argument, it is NOT standard to pass a contained procedure (a procedure contained inside another procedure.) The standard has a note saying how this should work if a compler should choose to support this as an extension, and indeed Intel Fortran does.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
In that same setup as above, there is a variable declared in caller_sub called RTEMP. I need to use RTEMP in the FEX_FUN subroutine, but that variable isn't passed into FEX_FUN as an argument. So, conceptually, how do I give a subroutine access to a variable that has been used previously in other subroutines, without actually passing it in as an argument? I'm sure this is exceedingly easy to do, but probably so easy that I'm overlooking it (as we engineers tend to do).
Thanks.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I like the easy ones...
Put it in a MODULE and USE the module in the routines in which you want the variable to be available.
MODULE MYGLOBALS
INTEGER I
REAL*8 R
CHARACTER*100 FILENAME
END MODULE
SUBROUTINE FOO(A,B,C,D, E, J,K)
USE MYGLOBALS
INTEGER J,K
REAL*8 A,B,C,D,E
R=A
I=J
RETURN
END SUBROUTINE FOO

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