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

Fortran DLL - Multiple Versions

smedvedoff
Beginner
1,201 Views

I built two versions of a Fortran DLL, and linked the executable that uses them with the .lib from Vers1. Since the calling signature for the DLL routines is the same in both DLLs, I believe I should be able to use the Vers2 DLL without relinking, provided I load the Vers2 DLL and get the proc addresses of its routines. Here's my setup:

module Proc_Mod

interface

subroutine Sub1( IUnit)

INTEGER IUnit

end subroutine

end interface

pointer(Sub1_Ptr, Sub1)

end module Proc_Mod

Subroutine Load_It

use kernel32

use Proc_Mod

Lib_ID = loadlibrary("Vers2"C)

Sub1_Ptr = getprocaddress(Lib_ID, "Sub1"C)

Return

End

Subroutine Call_It

use Proc_Mod

IUnit = 10

Call Sub1(IUnit)

Return

End

When I try to link, I get the following error message:

1>Call_It.obj : error LNK2005:Sub1 already defined in Proc_Mod.obj

Which I don't understand because I'm not redefining it in Call_It (as far as I can tell), I'm using it.

When I try it without a module, putting the pointers inCOMMON instead, it links, but it calls the version of Sub1 in the Vers1 DLL. I assume this is because it's doing implicit linking, resolving the reference from the .lib file rather than from the Sub1_Ptr.

Any help would be appreciated.

Thanks,

Steve

0 Kudos
12 Replies
Steven_L_Intel1
Employee
1,201 Views
I can't reproduce the problem based on what you posted here. I took that code and built a DLL from it. It compiled and linked without error. Is this REALLY what your code has? Why are you linking to sub1's library at all? You shouldn't if you're using LoadLibrary.
0 Kudos
smedvedoff
Beginner
1,201 Views

Steve,

I changed the routine names and omitted code because it's proprietary, so it's not exactly the same, although the structure is. Sorry for not testing it first. Seemed like it was a valid representation of what I'm doing. I'll try to identify what's different.

If I don't link to sub1's .lib, then I get an unresolved external symbol link error for sub1. How do I avoid that?

Thanks,

Steve

0 Kudos
Steven_L_Intel1
Employee
1,201 Views
You avoid it by doing exactly what you showed in the code you posted. Make sure that there is no other declaration of sub1 in your code.
0 Kudos
smedvedoff
Beginner
1,201 Views

Steve,

I didn't understand your response, so looking back at the thread I think there was a misunderstanding. The code I posted is in the executable that calls the DLL, not the DLL itself. So when you say you took the code and built a DLL from it, that's not what I'm doing. My DLL, which contains sub1, has already been built, and I am now attempting to access it in a separate executable using the code I posted. When I try to build that executable I get the link error that I originally posted. And when I build that executable, I have to have the .lib file in the project or I get unresolved references. Sorry for the confusion.

- Steve

0 Kudos
Steven_L_Intel1
Employee
1,201 Views
Actually, that's what I thought you were doing. I said I built a DLL only because you didn't supply a main program. Either way, the code you showed should not require linking against the DLL's .lib.
0 Kudos
smedvedoff
Beginner
1,201 Views

Steve,

Here's another example of the same problem using actual code. I'm using an include file rather than a module:

My include file:

C
interface

subroutine Sub1( IUnit )
INTEGER IUnit
end subroutine
C
end interface
C
integer ProcID
pointer(Sub1_ptr, Sub1)
C
C
Common /SUBCOM/ ProcID, Sub1_ptr

Routine 1:

SUBROUTINE LoadDLL ()

use kernel32
C
Include 'Subcom.inc'
C
CSet up a pointer to the routine of interest
D4SciGuid_ProcID = loadlibrary("c:Sub1_Dll.dll")
C
Sub1_ptr = getprocaddress(ProcID, "Sub1"C)
C
Return
End

Routine 2:

Subroutine TestSub1

Include 'Subcom.inc'
C
Return
End

Routine 3:

SUBROUTINE TestSub2

INCLUDE 'Subcom.inc'
C
Return
End

Compiler Output:

1>TestSub1.obj : error LNK2005: SUB1 already defined in TestSub2.obj

1>LoadDLL.obj : error LNK2005: SUB1 already defined in TestSub2.obj

Thanks for your help,

Steve



0 Kudos
Steven_L_Intel1
Employee
1,201 Views
Works for me with ifort 10.0.026. I suppose I should have asked you this before - which compiler and version are you using?
0 Kudos
Steven_L_Intel1
Employee
1,201 Views
Also, on what OS type are you building this? I note that the linker error omits the leading underscore from SUB1 in the message, but your test code would give other errors when built on x64 where there are no leading underscores.
0 Kudos
smedvedoff
Beginner
1,201 Views

Steve,

I'm using ifort 10.0.026 as well. My OS is Windows XP.

I found a posting of a similar problem by BenIFKC (7-5-2007)- "Link Warning About Variables Defined Multiple Times". In your response you said that you could reproduce his problem, but only if you set QZERO. I tried unsetting QZERO and the errors went away, however I can't keep this setting as this is legacy code with many uninitialized variables. Also, in BenIFKC's posting his were warnings as opposed to errors. His warning was LNK4006. If I could convert these to warnings rather than errors that would be a great step in the right direction.

Thanks,

Steve

0 Kudos
Steven_L_Intel1
Employee
1,201 Views
Yep - that's exactly the problem. You can change the error to a warning by adding:

/link /force:multiple

to the command line. Let me also suggest trying /Qsave without /Qzero.

Please report this to Intel Premier Support and reference T78852-CP. This bug has not yet been fixed - your reporting it will help accelerate that process.
0 Kudos
smedvedoff
Beginner
1,201 Views

Steve,

Thanks for your help. I will report this to Intel Premier Support.

I tried adding /link /force:multiple to the command line, but got

"ifort: Command line error; no files specified"

I added it in the Fortran->Command Line->Additional Options window, but I suspect I'm not doing it correctly. Could you tell me how I shouldadd it?

Thanks again,

Steve

0 Kudos
Steven_L_Intel1
Employee
1,201 Views
On the command line, you put this at the end of the line. Everything after /link is passed to the linker.

In Visual Studio 2005, they've dropped the property for this so just type in /force:multiple under Command Line on the Linker (not Fortran) property page.
0 Kudos
Reply