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

DLL Considerations

Nick2
New Contributor I
454 Views

I have two DLLs that I'm interested in.  Let's call them Main.dll and Plugin.dll, both written in Fortran.

Plugin.dll needs to access various functions and COMMONs from Main.dll.  Ok, so I added a few

      !DIR$ ATTRIBUTES DLLIMPORT :: /WHATEVER/

kind of statements, and created a module definition file to go along with Main.dll.  The user of Main.dll and Plugin.dll loads everything into memory, and life is good.

Now for the problem.  The user of Main.dll wants to run two instances of Main.dll.  So, in order to give each instance of Main.dll its own COMMON blocks, I copy Main.dll into C:\Windows\Temp\{runtime generated GUID}\{runtime generated GUID}.dll and C:\Windows\Temp\{another runtime generated GUID}\{another runtime generated GUID}.dll.  But now, I get a MessageBox stating "The program can't start because Main.dll is missing from your computer.  Try reinstalling the program to fix this problem".

So ... how do I tell Plugin.dll that, nevermind, instead of Main.dll you should now link up with {runtime generated GUID}.dll?

 

0 Kudos
5 Replies
Steven_L_Intel1
Employee
454 Views

I don't think you can do this for DLLs that are incorporated by linking against their export library. You may need to use LoadLibrary and GetProcAddress to load the individual DLLs and access definitions in them. There's a big "gotcha" here, though - the COMMON blocks. This simply will not work. Instead of shared variables you'll need to write "get" routines that return a pointer to the shared data and access via the pointers.

Sounds like a lot of work and a rather major upheaval of the application structure.

What problem is being solved by the two independent versions of the DLL? Maybe there's another way.

0 Kudos
jimdempseyatthecove
Honored Contributor III
454 Views

Are you really asking for how a single process (application) can load and use two instances of the same .DLL?

If so, then consider having Main.dll contain a context type (possibly private type), then have your process call a function/subroutine to obtain a handle (of your design) of/(pointer to) an allocated context. The process/application can then obtain as many handles as necessary (much like a Window handle), This does require the using process must pass the handle on calls.

Jim Dempsey

0 Kudos
Nick2
New Contributor I
454 Views

Main.dll was always meant to operate on a healthy number of COMMON variables, and to operate on a single set of inputs; after it's done, we simply unload Main.dll (or kill the entire executable).  However, now we need to solve two sets of inputs simultaneously, so we need to load two separate instances of Main.dll (because all of the data is stored in global memory).  I'm not familiar with using different contexts, if this would solve the problem just as well as my file-copying, I would appreciate if you can point me at a few API functions.

If there's a way to use LoadLibrary to replace these statements:

      !DIR$ ATTRIBUTES DLLIMPORT :: /WHATEVER/

I'm open to that approach as well.

 

0 Kudos
Steven_L_Intel1
Employee
454 Views

For procedures, it's not difficult to use dynamic loading. For individual variables, it's a bit trickier but you can still do it if you use pointers and indirection, since the exported symbol in the DLL resolves to a pointer to the variable. For COMMON, there's no good way to say "here's a pointer that's the base of the COMMON".

Well, I fibbed a bit there. It may be possible through an Intel compiler feature I try to pretend doesn't exist: Dynanic Common. The idea is that you compile with the /Qdyncom option naming the common blocks you want to be dynamically allocated. You then write a procedure called _FTN_ALLOC (or call FOR__SET_FTN_ALLOC to specify such a procedure) that stores as one of its argument the address of the base of the COMMON. While this is more often used with dynamic allocation, I don't see any reason why you couldn't use LoadLibrary and GetProcAddress to get the exported pointer and return that. No, I'm not going to write you an example. See the "Allocating Common Blocks" topic in the compiler documentation for more details. I note that the docs say that the allocation routine must be written in C, but that's not really true - it could be written in Fortran with the appropriate C interoperability features.

If you go this route, do some tests to see what GetProcAddress returns. It might actually be the COMMON base address

I will caution you that in the past there have been proposals to drop the "dynamic common" feature, but I am not aware of any current activity in this area.

0 Kudos
IanH
Honored Contributor II
454 Views

If moving away from common isn't an option, then I'd be inclined to wrap main_dll with an exe, and have plugin_dll then interact with multiple processes of that exe.

0 Kudos
Reply