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

Use of modules in a DLL

michael_green
Beginner
713 Views
Hi all,
I'm making my first attempts at using DLLs and there are some things I don't understand. I have a main program, a module defining some global variables, and a DLL. Both the main program and the DLL refer to(use) the module. The module is not contained in the DLL
I find that the module's variables are defined correctly in the main program but are undefined in the DLL
I have read about DLLEXPORT and DLLIMPORT in Etzel & Dickinson but they clearly talk about giving these attributes to data objects ina module which is within the DLL, and mine is not.
Please can someone advise me what to do?
With many thanks in advance,
Mike
0 Kudos
9 Replies
Steven_L_Intel1
Employee
713 Views
You have two copies of the module variables - one within the DLL and one in the executable. They don't share the same memory.

What you want to do is add the DLLEXPORT attribute to the module variables. When you build the DLL, it will export the variables. When you USE the module in the executable, it will treat the DLLEXPORT as a DLLIMPORT with the result being that the variables are shared.

You will get a harmless linker warning when you link the DLL about an imported symbol defined locally. Ignore it.
0 Kudos
michael_green
Beginner
713 Views
Steve,
Thanks for your help. Unfortunately it still doesn't work. The module is called FMISGLOBALS and it defines, for example, a variable called FMIS$COMMON. I have applied the DLLEXPORT attribute to FMIS$COMMON.
When I do a DUMPBIN /exports on the DLL I see that the variable exported is called FMISGLOBALS_mp_FMIS$COMMON. This looks significant but I don't know what it means. Any suggestions?
With many thanks
Mike
0 Kudos
Steven_L_Intel1
Employee
713 Views
It means it's FMIS$COMMON defined in module FMISGLOBALS. If you built the EXE with a USE of that module, it should find it, and require you to link against the export library of the DLL.

If you need more help with this, submit an example project and an explanation of the problem to Intel Premier Support and we'll look at it.
0 Kudos
durisinm
Novice
713 Views


sblionel wrote:
You have two copies of the module variables - one within the DLL and one in the executable. They don't share the same memory.

What you want to do is add the DLLEXPORT attribute to the module variables. When you build the DLL, it will export the variables. When you USE the module in the executable, it will treat the DLLEXPORT as a DLLIMPORT with the result being that the variables are shared.

You will get a harmless linker warning when you link the DLL about an imported symbol defined locally. Ignore it.

Huh? Why does USEing the module in the executable cause the DLLEXPORT to be treated as a DLLIMPORT?

Mike

0 Kudos
Steven_L_Intel1
Employee
713 Views
It's something PowerStation did and it makes life a heck of a lot simpler. Otherwise you would need to create two different versions of the .mod, one for building the DLL and one you use for building against the DLL. I too was skeptical of this at first, and we didn't do it for a while, but once I thought about what a user would have to do without this feature, I was sold.
0 Kudos
michael_green
Beginner
713 Views
 
0 Kudos
michael_green
Beginner
713 Views
I've put together a sample console program that demonstrates the problem. Here's the main program:
program DLLtest
use dfwin
use globals
implicit none
real*4pi
integer*4hpi,iret
pointer(p,rtn_calc_pi)
interface
subroutine rtn_calc_pi(pi)
real*4pi
end subroutine
end interface
reala = 355
realb = 113
!Get handle of the calc_pi dll
hpi = loadlibrary("calc_pi.dll"C)
if(hpi==0)then
type *,'Error locating calc_pi.dll'
call exit
end if
!Get address of the calc_pi function
p = getprocaddress(hpi,"CALC_PI"C)
if(p==0)then
type *,'Error locating routine calc_pi in calc_pi.dll.'
call exit
end if
call rtn_calc_pi(pi) !Calculate pi
iret = freelibrary(hpi)
type *,'pi = ',pi
end program DLLtest
Here's the globals module
module globals
implicit none
!DEC$ ATTRIBUTES DLLEXPORT :: reala,realb
real*4reala,realb
end module
And here's the DLL
subroutine calc_pi(pi)
!DEC$ ATTRIBUTES DLLEXPORT::calc_pi
use globals
real*4pi
pi = reala/realb
return
end subroutine calc_pi
I'm compiling and linking using default settings for everything and I don't get any warning messages, however, the values of reala and realb remain undefined within the DLL when the program runs.
Any suggestions?
Thanks a million
Mike
0 Kudos
Steven_L_Intel1
Employee
713 Views
Oh, you're using LoadLibrary to load the DLL! No wonder it doesn't work. This prevents the module variables from being "hooked up". Why not do away with the LoadLibrary and just link against the DLL export library?

I suppose you can also do a GetProcAddress on the module variables and use the integer pointer extension to reference them. You may have to do an extra level of indirection with these (what you get may be a pointer to a pointer to the variable.)
0 Kudos
Intel_C_Intel
Employee
713 Views
Hello,
I think that values of variables reala and realb when Calc_Pi executes are not 355 and 113. When Main program defines values of reala, realb the DLL doesn't know about it at all. DLL's reala and realb NOT are the same Main's reala and realb. It two different executable 'programs'.
The best explanation is:
imagine that we have two Main programs -- different projects.
at first DLLTest1 we will write:

reala = 355
realb = 113

at another DLLTest2 we will write:

reala = 999
realb = 777
Compile two different programs DLLTest1 and DLLTest2.
Run them and give them the SAME DLL which contains Calc_pi. First we run DLLTest1 then DLLTest2 and don't close them.

If DLL's variables and Main's variables reala and realb are the same then DLL's reala first will be 355 and after some time 999. But it means that DLLTeat1's and DLLTest2's reala are in the SAME memory adress!!! It isn't, of course, at least because it's separate exes not threads in one process.
0 Kudos
Reply