Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
28991 Discussions

problem accessing functions within dll

marcp
Beginner
642 Views
Hello all,

I'm just returning to Fortran after a long sojourn. I have some f90 code that I am trying to wrap in a dll so I can call it from elsewhere. I'm having trouble getting everything to hang together.

In the example I include below I have a single exported function that is simply a wrapper for another function:

REAL*8 FUNCTION CylinderModel( R, Theta, Incl, Decl, Intensity, Radius, Depth_Top, Depth_Bottom )
!
!DEC$ ATTRIBUTES C, reference, ALIAS:"CylinderModel", DLLEXPORT::CylinderModel
! Variables
IMPLICIT NONE

INTERFACE
REAL*8 FUNCTION CYLNDR(I_T, A, H, I_0, D_0, R, THETA, Z)
REAL*8 I_T ! Total magnetization (remanent plus induced)
REAL*8 A ! Radius of the cylinder
REAL*8 H ! Height of the cylinder
REAL*8 I_0, D_0 ! Inclination and declination of the earth's field
REAL*8 I_P, D_P ! Inclination and declination of the polarization
REAL*8 R,THETA,Z ! Evaluation point of the field w.r.t top of cylinder
end FUNCTION
end interface

INTEGER*4 Cells
REAL*8 CellSize
REAL*8 Incl, Decl, Intensity, Radius, Depth_Top, Depth_Bottom
REAL*8 R, Theta
REAL*8 Cylndr

! Body of CylinderMode
CylinderModel = CYLNDR(Intensity,Radius,Depth_Bottom,Incl,Decl,R,Theta,Depth_Top)

end Function CylinderModel

REAL*8 FUNCTION CYLNDR(I_T, A, H, I_0, D_0, R, THETA, Z)

IMPLICIT NONE
INTERFACE
REAL*8 FUNCTION INFCYL(I_T, A, I_0, D_0, I_P, D_P, R, THETA, Z)
REAL*8 I_T ! Total magnetization (remanent plus induced)
REAL*8 A ! Radius of the cylinder
REAL*8 I_0, D_0 ! Inclination and declination of the earth's field
REAL*8 I_P, D_P ! Inclination and declination of the polarization
REAL*8 R,THETA,Z ! Evaluation point of the field w.r.t top of cylinder
end function
end interface

! Formal Parameters:
REAL*8 I_T ! Total magnetization (remanent plus induced)
REAL*8 A ! Radius of the cylinder
REAL*8 H ! Height of the cylinder
REAL*8 I_0, D_0 ! Inclination and declination of the earth's field
REAL*8 I_P, D_P ! Inclination and declination of the polarization
REAL*8 R,THETA,Z ! Evaluation point of the field w.r.t top of cylinder
REAL*8 ZABS

!We are assuming no remanent magnetization
I_P = I_0
D_P = D_0

ZABS = ABS(Z)
IF(H.LT.0) THEN
CYLNDR = INFCYL(I_T, A, I_0, D_0, I_P, D_P, R, THETA, ZABS)
ELSE
CYLNDR = INFCYL(I_T, A, I_0, D_0, I_P, D_P, R, THETA, ZABS) &
& -INFCYL(I_T, A, I_0, D_0, I_P, D_P, R, THETA, ZABS+H)
ENDIF
RETURN
END

I am getting the following compile time errors with this code:
Z:\Fortran\FGoldak\Cylinder.f90(29): error #6409: This name has already been used as an external procedure name. [CYLNDR]
REAL*8 Cylndr
---------^
Z:\Fortran\FGoldak\Cylinder.f90(32): error #7977: The type of the function reference does not match the type of the function definition. [CYLNDR]
CylinderModel = CYLNDR(Intensity,Radius,Depth_Bottom,Incl,Decl,R,Theta,Depth_Top)
^
Z:\Fortran\FGoldak\Cylinder.f90(32): error #8000: There is a conflict between local interface block and external interface block. [CYLNDR]
CylinderModel = CYLNDR(Intensity,Radius,Depth_Bottom,Incl,Decl,R,Theta,Depth_Top)
--------------------^

and so on...

Inititally the sub functions were just defined as variables like this:
REAL*8 CYLNDR etc.. but that didn't compile either


Compiling with Intel Visual Fortran 11.0.072 [IA-32]...
ifort /nologo /Od /gen-interfaces /warn:interfaces /module:&quotDebug\" /object:&quotDebug\" /traceback /check:bounds /libs:dll /threads /dbglibs /c /Qvc8 /Qlocation,link,&quotC:\Program Files\Microsoft Visual Studio 8\VC\bin" &quotZ:\Fortran\FGoldak\Cylinder.f90"
Z:\Fortran\FGoldak\Cylinder.f90(30): error #6418: This name has already been assigned a data type. [CYLNDR]
REAL*8 CYLNDR
---------^
Z:\Fortran\FGoldak\Cylinder.f90(32): error #7977: The type of the function reference does not match the type of the function definition. [CYLNDR]
CylinderModel = CYLNDR(Intensity,Radius,Depth_Bottom,Incl,Decl,R,Theta,Depth_Top)
^
Z:\Fortran\FGoldak\Cylinder.f90(32): error #6633: The type of the actual argument differs from the type of the dummy argument. [INTENSITY]
CylinderModel = CYLNDR(Intensity,Radius,Depth_Bottom,Incl,Decl,R,Theta,Depth_Top)
------------------------^


I'm sure its a simple thing but I've been reading and banging my head on this for 2 days.

HOW do I declare a function so that it can be called from elsewhere in the same file??

thanks

Marc Pelletier
Goldak Airborne Surveys
0 Kudos
4 Replies
Les_Neilson
Valued Contributor II
642 Views

removing the statement
REAL*8 Cylndr
the code shown compiles without error.

The variables I_P, D_P are unused in the Interface block.
VariablesCells and CellSize are unused variables in CylinderModel - all of which may be due to snipping out some code from the real world source ?

Les
0 Kudos
marcp
Beginner
642 Views
Quoting - Les Neilson

removing the statement
REAL*8 Cylndr
the code shown compiles without error.

The variables I_P, D_P are unused in the Interface block.
VariablesCells and CellSize are unused variables in CylinderModel - all of which may be due to snipping out some code from the real world source ?

Les

Thanks Les,

I guess I was kind of sloppy n my cut and paste, and not at all clear on the interface issue. The original code just exposed the function as a variable, as in the code included above. I started from scratch and rebuilt the dll using interface sections for each function. With a bunch of other mods I got it to compile. But I have a couple of questions:

Is there any way to declare a function so that it is visible to a bunch of other functions without having to build interface sections constantly? Is that what modules are for? I guess I would like to find a document that describes all of the scoping rules and options? The help file seems kind of circular on these topics.

cheers,

Marc Pelletier

0 Kudos
Steven_L_Intel1
Employee
642 Views
Yes, this is what modules are for. There are any number of good texts on the Fortran language that cover issues such as scoping, or you could try reading the Fortran 2003 standard (which can be obtuse in many places.)

For a DLL, a reasonable implementation is one or modules which contain module procedures, each with a DLLEXPORT attribute directive. When the DLL is built, the compiler will also create compiled module (.mod) files. You will need to make these visible to the user of the DLL - add them to the INCLUDE path. The DLLEXPORTs will turn into DLLIMPORTs on USE, which is handy.


0 Kudos
bmchenry
New Contributor II
642 Views

Since you're just returning to fortran, many changes! Time to brush up on all the changes!
I recommend getting a book or two on Fortran90, 2003, etc.
here's a resource with listings of books, etc:
http://www.fortran.com/metcalf.htm

Of those, I'd recommend:
Fortran 90 Programming - Ellis, Philips, Lahey, Addison Wesley, Wokingham, 1994, ISBN 0-201-54446-6.
or a more recent book on 2003 by one or more of the authors or Metcalf.

Brian
0 Kudos
Reply