- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
I am trying to call procedures defined in a module in a dll that I created myself. I am mostly following the instructions that I found here. In particular, for 'simplicity' purposes, I am trying to avoid using the !DEC$ ATTRIBUTES DLLIMPORT in the main. Indeed, I thought that the process described in the link above for sharing data through modules could work with procedures. And most times it does.
My problems comes when I call a routine whose arguments' dimensions are contained in another module in the library (the main, outside the library, calls a subroutine which is in a module in the library, and uses another module of the library for dimensions). In those cases, the compiler tells me that the constants used for the dimensions are unresolved symbols in the main. But they are NOT USED in the main. To be clearer, I included a MWE that reproduces the problem:
The following are the two modules compiled in the dll:
MODULE constantsMod
integer :: nStates
end MODULE
MODULE testMod
contains
subroutine setupConstants(nIn)
!DEC$ ATTRIBUTES DLLEXPORT, ALIAS : "setupConstants" :: setupConstants
use constantsMod
implicit none
integer, intent(in) :: nIn
nStates = nIn
end subroutine
subroutine test(nX, nY)
!DEC$ ATTRIBUTES DLLEXPORT, ALIAS : "test" :: test
use constantsMod
implicit none
real*8, intent(in) :: nX(nStates)
real*8, intent(out) :: nY(nStates)
print*, nX, nStates
nY = nX
end subroutine
subroutine test2(nStates, nX, nY)
!DEC$ ATTRIBUTES DLLEXPORT, ALIAS : "test2" :: test2
implicit none
integer, intent(in) :: nStates
real*8, intent(in) :: nX(nStates)
real*8, intent(out) :: nY(nStates)
print*, nX, nStates
nY = nX
end subroutine
end MODULE
The main is compiled on its own (and marked to be dependent on the library in Visual Studio: the library and the main are two projects in the same solution, with the same output directory so that the dll is in the same folder as the exe), and is as follows:
PROGRAM main
use testMod
implicit none
real*8 :: nX(6), nY(6)
CALL setupConstants(6)
CALL test(nX, nY)
CALL test2(6, nX, nY)
end program
When compiling the previous main, I get: "Error 1 error LNK2001: unresolved external symbol _CONSTANTSMOD_mp_NSTATES main.obj "
When commenting out the call to test and leaving test2, no problem. If I stop using testMod and add three !DEC$ DLLIMPORT, no problem either. However, because in my real project I have MANY functions being exported and I'd love to not have to DLLIMPORT all of them.
Now, I understand that the reference I cited above only mentions sharing DATA through modules, and not procedures. I am also expecting the problem to come from the interfaces that are generated by the module. I was just wondering if there was a workaround that didn't involve writing the many DLLIMPORT statements I would need.
Thanks!
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I just gave your source code a whirl... and I didn't see the error. See below for the command line options I used. What are you doing differently?
That module variable is part of the characteristics of a dummy argument of the module procedure, so I could envisage particular reasons why an implementation would want to reference it - perhaps as part of argument consistency checking, for example. If an explicit interface isn't accessible at the point of call the compiler doesn't know about the characteristics of the module variable and so can't reference it as part of any checks.
Have you tried putting DLLEXPORT on the variable?
>ifort /dll /check:all /warn:all /standard-semantics /Od "2014-10-18 dll-dll.f90" Intel(R) Visual Fortran Intel(R) 64 Compiler XE for applications running on Intel(R) 64, Version 15.0.0.108 Build 20140726 Copyright (C) 1985-2014 Intel Corporation. All rights reserved. Microsoft (R) Incremental Linker Version 10.00.40219.01 Copyright (C) Microsoft Corporation. All rights reserved. "-out:2014-10-18 dll-dll.dll" -dll "-implib:2014-10-18 dll-dll.lib" "2014-10-18 dll-dll.obj" Creating library 2014-10-18 dll-dll.lib and object 2014-10-18 dll-dll.exp >ifort /check:all /warn:all /standard-semantics /Od "2014-10-18 dll-exe.f90" "2014-10-18 dll-dll.lib" Intel(R) Visual Fortran Intel(R) 64 Compiler XE for applications running on Intel(R) 64, Version 15.0.0.108 Build 20140726 Copyright (C) 1985-2014 Intel Corporation. All rights reserved. Microsoft (R) Incremental Linker Version 10.00.40219.01 Copyright (C) Microsoft Corporation. All rights reserved. "-out:2014-10-18 dll-exe.exe" -subsystem:console "2014-10-18 dll-exe.obj" "2014-10-18 dll-dll.lib"
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I can get the error if I compile the main program /debug. I'll ask the developers if this is necessary.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This may be an issue of inter-file IPO where the function test is attempted to be inlined. As an experiment, try removing inter-file IPO (intra-file IPO is ok).
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
One can't inline from a DLL. I will comment that the use of NSTATES in the declaration of the dummy argument is probably the important part. In some cases the calling code needs to evaluate variables in the specification expression, but not in this case. (I will try a case where it is needed.) Here, the reference to NSTATES is in the debug information but it should be skipped since it isn't exported.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
>>One can't inline from a DLL
Then wouldn't it go to reason that one can't inline from a static library?
In earlier versions of IVF, when IPO came out, when the sources to a static library were locatable on a system where an application were compiled using this static library, I've experienced situations where the inlining would find those sources and incorporate them into the inlining...even when the sources were for a newer generation of code than that of the library being linked to. Now, this said, this may no longer be the case, but to the best of my knowledge I experienced this on one or more occasions. Regardless, it is easy enough to test for, just turn off inter-file IPO and perform a build. If this corrects for the problem then this is an old bug/quirk and should be reported. If it does nothing to fix the problem, then it wasted only one build time.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
No, one CAN inline from a static library if it was built with /Qipo. But once the linker is invoked - necessary to build a DLL - the intermediate code is gone.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Escalated as issue DPD200362319. You could add the linker option /force:unresolved to allow the link to complete.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you all for your help. Adding the /force:unresolved linker option did solve the problem. Compiling in Release Mode too... I am not used to Visual Studio and /debug /release options, and didn't even think of checking the Release mode...
Thanks!
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page