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

Using 2 DLLs containing "the same named" procedures

Intel_C_Intel
Employee
596 Views

Hello

What if two DLLs contain procedures with the same name. How can I indicate from wich DLL this procedure must be loaded? I'd like to use implicit linking. And what if I'd like to use both procedures in main program, how in this case give them different aliases? Thanks for answers.

0 Kudos
5 Replies
anthonyrichards
New Contributor III
596 Views

Look at a very recent thread where GetProcAddress is used, along with pointers, to get the location of a DLL routine/function. Just save a seperate address for the two procedures after you have obtained them using the code you will find in the thread

http://softwareforums.intel.com/en-us/forums//topic/51224

0 Kudos
Jugoslav_Dujic
Valued Contributor II
596 Views
It's even possible to do it with static binding (including .lib files into the project), but you have to mess with manual creation of .lib files -- you will have to "rename" one set of imported routines using .DEF file and LIB.exe, for the purpose of linking. See hints in this thread.
0 Kudos
Intel_C_Intel
Employee
596 Views

Tanks for answers to both.

1. Explicit linking in the same named DLL's procedures

For explicit linking I understood.

DLL1

subroutine ImportedProcedure( number )
!DEC$ ATTRIBUTES STDCALL, DLLEXPORT, DECORATE, ALIAS: "ImportedProcedure" :: ImportedProcedure

implicit none

integer, intent(in) :: number

print '(1x, a, i)', "From DLL #1: ", number
end subroutine ImportedProcedure

DLL2

subroutine ImportedProcedure( number )
!DEC$ ATTRIBUTES STDCALL, DLLEXPORT, DECORATE, ALIAS: "ImportedProcedure" :: ImportedProcedure

implicit none

integer, intent(in) :: number

print '(1x, a, i)', "From DLL #2: ", number
end subroutine ImportedProcedure

Main Program

program ExplicitLinking
use kernel32
 implicit none

print *, "Separately one of them"
call SeparatelyOneOfThem()
print *, "Simultaneously both"
call SimultaneouslyBoth()

read *

contains
subroutine SimultaneouslyBoth
interface
subroutine ImportedProcedure1( number )
!DEC$ ATTRIBUTES STDCALL :: ImportedProcedure1
integer, intent(in) :: number
end subroutine ImportedProcedure1

subroutine ImportedProcedure2( number )
!DEC$ ATTRIBUTES STDCALL :: ImportedProcedure2
integer, intent(in) :: number
end subroutine ImportedProcedure2
end interface

integer Lib1, Lib2, Status

pointer( ptrImportedProcedure1, ImportedProcedure1 )
pointer( ptrImportedProcedure2, ImportedProcedure2 )

Lib1 = LoadLibrary( "DLL1.dll"C )
  ; Lib2 = LoadLibrary( "DLL2.dll"C )

ptrImportedProcedure1 = GetProcAddress( Lib1, "ImportedProcedure"C )
ptrImportedProcedure2 = GetProcAddress( Lib2, "ImportedProcedure"C )

call ImportedProcedure1( 1 )

call ImportedProcedure2( 2 )

Status = FreeLibrary( Lib1 )
Status = FreeLibrary( Lib2 )
end subroutine SimultaneouslyBoth

subroutine SeparatelyOneOfThem
interface
subroutine ImportedProcedure( number )
!DEC$ ATTRIBUTES STDCALL :: ImportedProcedure
integer, intent(in) :: number
end subroutine ImportedProcedure
end interface

integer Lib1, Lib2, Status

pointer( ptrImportedProcedure, ImportedProcedure )

Lib1 = LoadLibrary( "DLL1.dll"C )
Lib2 = LoadLibrary( "DLL2.dll"C )

ptrImportedProcedure = GetProcAddress( Lib1, "ImportedProcedure"C )

call ImportedProcedure( 1 )

ptrImportedProcedure = GetProcAddress( Lib2, "ImportedProcedure"C )

call ImportedProcedure( 2 )

Status = FreeLibrary( Lib1 )
Status = FreeLibrary( Lib2 )
end subroutine SeparatelyOneOfThem
end program ExplicitLinking

All works:

Separately one of them
From DLL #1: 1
From DLL #2: 2
Simultaneously both
From DLL #1: 1
From DLL #2: 2

2. Source code editing in the same named DLL's procedures

Another way if source code available is to edit them by giving dofferent names to procedures.

2.1. Editing procedures names in sour ce code

DLL1

subroutine ImportedProcedure1( number )
!DEC$ ATTRIBUTES STDCALL, DLLEXPORT, DECORATE, ALIAS: "ImportedProcedure1" :: ImportedProcedure1

implicit none

integer, intent(in) :: number

print '(1x, a, i)', "From DLL #1: ", number
end subroutine ImportedProcedure1

DLL2

subroutine ImportedProcedure2( number )
!DEC$ ATTRIBUTES STDCALL, DLLEXPORT, DECORATE, ALIAS: "ImportedProcedure2" :: ImportedProcedure2

implicit none

integer, intent(in) :: number

print '(1x, a, i)', "From DLL #2: ", number
end subroutine ImportedProcedure2

2.2. Changing only aliases of procedures

DLL1

subroutine ImportedProcedure( number )
!DEC$ ATTRIBUTES STDCALL, DLLEXPORT, DECORATE, ALIAS: "ImportedProcedure1" :: ImportedProcedure

implicit none

integer, intent(in) :: number

print '(1x, a, i)', "From DLL #1: ", number
end subroutine ImportedProcedure

DLL2

subroutine ImportedProcedure( number )
!DEC$ ATTRIBUTES STDCALL, DLLEXPORT, DECORATE, ALIAS: "ImportedProcedure2" :: ImportedProcedure

implicit none

integer, intent(in) :: number

print '(1x, a, i)', "From DLL #2: ", number
end subroutine ImportedProcedure

By applying one of this methods procedures will have different names in DLL. In this case it does not matter wich method of linking, explicit or implicit, are using in next step.

3. Implicit linking in the same named DLL's procedures

Am I understand this case correct? Just modify .lib file by "renaming" ImportedProcedure to ImportedProcedure1 for DLL1 and to ImportedProcedure2 for DLL2. So for source code wich imports DLL's procedures this procedures will have different names. But how do that using LIB.exe? What files are required?LIB in input works with object files (.obj)and COFF files (.lib). Usually with DLL goes .lib (not COFF)and .dll :). Is it possible to do that using only this to files?

Ok. Let I have .obj, .lib and .dll file. To link as I want I should create .def file. But where should Iset calling conventions? Or after .obj it doesn't required: theyalready have been set as specified in ATTRIBUTES (like STDCALL)?

I understand that not so much people need to try something from what I described. May be someone will show me the "way"... And of course I'd like to continue discussion with Jugoslav for this case.

4. Suggestionfor IFC developers

It would be grate to have special attribute like DLLNAME. Just imagine:

interface
subroutine ImportedProcedur e1( number )
!DEC$ ATTRIBUTES STDCALL, DLLEXPORT, DECORATE, ALIAS: "ImportedProcedure", DLLNAME: "DLL1" :: ImportedProcedure1

integer, intent(in) :: number
end subroutine ImportedProcedure1
 subroutine ImportedProcedure2( number )
!DEC$ ATTRIBUTES STDCALL, DLLEXPORT, DECORATE, ALIAS: "ImportedProcedure", DLLNAME: "DLL2" :: ImportedProcedure2

integer, intent(in) :: number
end subroutine ImportedProcedure2
end interface

I think it quite possible to realise in compiler. To developers: "Pleeaase".

0 Kudos
Steven_L_Intel1
Employee
596 Views
There's no object language support for specifying a DLL name in conjunction with a global symbol, so a compiler can't deal with it. Dynamic activation is the only way to do this.
0 Kudos
jugoslavdujic2
Beginner
596 Views

Am I understand this case correct? Just modify .lib file by "renaming" ImportedProcedure to ImportedProcedure1 for DLL1 and to ImportedProcedure2 for DLL2. So for source code wich imports DLL's procedures this procedures will have different names. But how do that using LIB.exe? What files are required?LIB in input works with object files (.obj)and COFF files (.lib). Usually with DLL goes .lib (not COFF)and .dll :). Is it possible to do that using only this to files?

Ok. Let I have .obj, .lib and .dll file. To link as I want I should create .def file. But where should Iset calling conventions? Or after .obj it doesn't required: theyalready have been set as specified in ATTRIBUTES (like STDCALL)?

I understand that not so much people need to try something from what I described. May be someone will show me the "way"... And of course I'd like to continue discussion with Jugoslav for this case.

This page offers a fairly good explanation. Basically, you don't need to have an .obj file -- (it appears) you can make an import library solely using a .def file with EXPORTS statement, using LIB /DEF:MyDll.def, where you wrote the .def file. Of course, you have to know the name of dll's exports. However, like I said, you have to experiment yourself; I've never done that. If you have troubles, I can give it a try too, but I'm fairly busy these days.

Of course, you can set the calling conventions only during compiling/building, and they must match in the caller and the callee; there's no workaround for that. My understanding is that the import library looks roughly like:

SUBROUTINE __imp_WHATEVER()
CALL Function(LOC(DllAddress)+WHATEVEROffset)
END SUBROUTINE

where the two names match by default; however, you can (supposedly) change the first name via LIB+DEF, so that you don't have two __imp_WHATEVER's presented to the linker.
0 Kudos
Reply