- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi folks:
I've got a few DLLs that I'm trying to link into a larger program, and I'm getting some LNK2001 errors.
The first DLL has some general-purpose Gaussian integration routines. There are a few modules named gausspoints and gaussweights that define arrays used in Gaussian integration:
The gaussweights module is similar. There's also a module, gaussint, that USEs these "data" modules to perform the integration.
The second DLL contains a module function that is using a Gaussian integration routine found in the first DLL. Both this second DLL's function and the first DLL's integration routine are DLLEXPORT'ed. Here's the code of interest:
The USE of the gaussint module drags in the dependencies on the gausspoints and gaussweights modules.
Everything compiles OK, so I'm pretty sure that my project options settings for the second DLL are set up properly -- all of the USE statements seem to be able to see the .lib file and modules modules living a few folders over in the first DLL's ./Debug folder. But when it comes time to link, I see:
I'm a little confused as to whats going on here! I didn't think that I'd need to DLLEXPORT the "private" data that the first DLL is using, just to call one of its functions from a function in the second DLL.
Any ideas?
Thanks,
Elias Sabbagh
Victor Technologies, LLC
I've got a few DLLs that I'm trying to link into a larger program, and I'm getting some LNK2001 errors.
The first DLL has some general-purpose Gaussian integration routines. There are a few modules named gausspoints and gaussweights that define arrays used in Gaussian integration:
[bash]module gausspoints use kinds implicit none real(dk), parameter :: PTS2(1) = (/0.577350269189626_dk/) real(dk), parameter :: PTS3(2) = (/0.0_dk,0.774596669241483_dk/) real(dk), parameter :: PTS4(2) = (/0.339981043584856_dk,0.861136311594053_dk/) real(dk), parameter :: PTS5(3) = (/0.0_dk,0.538469310105683_dk,0.906179845938664_dk/) ! ...etc, etc. end module gausspoints[/bash]
The gaussweights module is similar. There's also a module, gaussint, that USEs these "data" modules to perform the integration.
The second DLL contains a module function that is using a Gaussian integration routine found in the first DLL. Both this second DLL's function and the first DLL's integration routine are DLLEXPORT'ed. Here's the code of interest:
[bash]module hankint use kinds implicit none type TSHankint_vars real(sk) r1 complex(sk) a end type TSHankint_vars type TDHankint_vars real(dk) r1 complex(dk) a end type TDHankint_vars interface hanki1 module procedure hanki1,dhanki1 end interface hanki1 contains complex(sk) function hanki1(a,r1,r2) result(res) !DEC$ ATTRIBUTES DLLEXPORT::hanki1 use gausint implicit none real(sk), intent(in) :: r1 ! lower limit of integral defining hanki1 real(sk), intent(in) :: r2 ! upper limit of integral defining hanki1 complex(sk), intent(in) :: a ! complex parameter of hanki1 type(TSHankint_vars) args args%a = a args%r1 = r1 ! Use 30 point Gauss integration to evaluate hanki1 if(.not.cgauss(30,hnkin1,r1,r2,res)) then ! FIX ME: Handle error here. endif contains complex(sk) function hnkin1 result(res) use scalpack implicit none real(sk), intent(in) :: r integer(ik) ierr, ncount complex(sk) sch0 ! scaled Hankel function of order 0 complex(sk) sch1 ! scaled Hankel function of order 1 call schank(args%a*r,sch0,sch1,ierr,ncount) res = r*exp( -(0.0_sk,1.0_sk)*args%a*(r-args%r1) )*sch1 end function hnkin1 end function hanki1 complex(dk) function dhanki1(a,r1,r2) result(res) use gausint implicit none real(dk), intent(in) :: r1 ! lower limit of integral defining hanki1 real(dk), intent(in) :: r2 ! upper limit of integral defining hanki1 complex(dk), intent(in) :: a ! complex parameter of hanki1 type(TDHankint_vars) args args%a = a args%r1 = r1 ! Use 30 point Gauss integration if(.not.cgauss(30,dhnkin1,r1,r2,res)) then ! FIX ME: Handle error here. endif contains complex(dk) function dhnkin1 result(res) use scalpack implicit none real(dk), intent(in) :: r integer(ik) ierr, ncount complex(dk) sch0 ! scaled Hankel function of order 0 complex(dk) sch1 ! scaled Hankel function of order 1 call schank(args%a*r,sch0,sch1,ierr,ncount) res = r*exp( -(0.0_dk,1.0_dk)*args%a*(r-args%r1) )*sch1 end function dhnkin1 end function dhanki1 end module hankint[/bash]
The USE of the gaussint module drags in the dependencies on the gausspoints and gaussweights modules.
Everything compiles OK, so I'm pretty sure that my project options settings for the second DLL are set up properly -- all of the USE statements seem to be able to see the .lib file and modules modules living a few folders over in the first DLL's ./Debug folder. But when it comes time to link, I see:
[bash]Error 1 error LNK2001: unresolved external symbol _GAUSSWEIGHTS_mp_WTS32 hankint.obj Error 2 error LNK2001: unresolved external symbol _GAUSSPOINTS_mp_PTS32 hankint.obj Error 3 error LNK2001: unresolved external symbol _GAUSSWEIGHTS_mp_WTS30 hankint.obj Error 4 error LNK2001: unresolved external symbol _GAUSSPOINTS_mp_PTS30 hankint.obj . . (etc) . Error 19 error LNK2001: unresolved external symbol _GAUSSWEIGHTS_mp_WTS3 hankint.obj Error 20 error LNK2001: unresolved external symbol _GAUSSPOINTS_mp_PTS3 hankint.obj Error 21 error LNK2001: unresolved external symbol _GAUSSWEIGHTS_mp_WTS2 hankint.obj Error 22 error LNK2001: unresolved external symbol _GAUSSPOINTS_mp_PTS2 hankint.obj Error 23 fatal error LNK1120: 22 unresolved externals Debug/besshankint.dll [/bash]
I'm a little confused as to whats going on here! I didn't think that I'd need to DLLEXPORT the "private" data that the first DLL is using, just to call one of its functions from a function in the second DLL.
Any ideas?
Thanks,
Elias Sabbagh
Victor Technologies, LLC
1 Solution
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
As you found, PARAMETER constants, which are not variables, cannot be DLLEXPORTed. By removing the PARAMETER attribute you make them into initialized variables, which are exportable.
Link Copied
4 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi folks:
OK, things get better if I remove the "parameter" attribute from the type definitions in the gausspoints module. At that point, everything links up fine.
Thanks,
Elias Sabbagh
Victor Technologies, LLC
OK, things get better if I remove the "parameter" attribute from the type definitions in the gausspoints module. At that point, everything links up fine.
Thanks,
Elias Sabbagh
Victor Technologies, LLC
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
As you found, PARAMETER constants, which are not variables, cannot be DLLEXPORTed. By removing the PARAMETER attribute you make them into initialized variables, which are exportable.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Quoting Steve Lionel (Intel)
As you found, PARAMETER constants, which are not variables, cannot be DLLEXPORTed. By removing the PARAMETER attribute you make them into initialized variables, which are exportable.
Shared PARAMETERs are typically contained in a module, then USE'd by the interested parites. For an application solution where all sources could potentially get re-compiled a dependency check can notice a change in module containingPARAMETER and thus recompile the module, and then the dependencies of that module. For a DLL that is not sourced in the solution this would not be possible (dependency recompile). Therefore, a PARAMETER in the DLL might differ from that in the application .AND. there would be no link time indication that there is a difference. (Never mind the fact that if you change parameter in a module used by a DLL that you ought to recompile the DLL too.)
Consider then if a PARAMETER is marked for DLLEXPORT that a name/content mangled entity could be created that is functionally (to the linker) equivalent to a template created function bodyfor C++. In C++ normal linking rules inhibit multiple functions with the same signature. However, code generated with templates can (usually do) have multiple files generate the same function w/ same signature. To "fix" this, the linker was changed to recognize template generated functions and for those functions the function body was used as a comparand. Should the multiple (template)functions with the same signature have the same contents for function body, then the linker would ignore the additional instance. Should the contents of the function body differ then an error is reported (i.e. template code changed between compiles of different sources using the template).
What my suggestion means is, with this change: DLLEXPORTed PARAMETERS are ASSERTED equal by the linker (else link fails with appropriate error message).
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Steve-
Thanks for the reply. I should have mentioned that I'm using version 12.1 of the compiler. The origianl code (which included the PARAMETER attributes) actually compiled and linked up fine using the old IVF 8.* compiler, so obviously something's been tightened up (or loosened!) since then.
I've got a lot of Fortran 2003/2008 to learn...
Elias Sabbagh
Victor Technologies, LLC
Thanks for the reply. I should have mentioned that I'm using version 12.1 of the compiler. The origianl code (which included the PARAMETER attributes) actually compiled and linked up fine using the old IVF 8.* compiler, so obviously something's been tightened up (or loosened!) since then.
I've got a lot of Fortran 2003/2008 to learn...
Elias Sabbagh
Victor Technologies, LLC
Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page