- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have a problem when calling loadlibrary with relative paths:
- compiled with default static libs, the loadlibrary does not work with relative paths after a call to DAXPY
- compiled with libs:dll, relative paths does not work at all
Details:
- intel fortran 2020 (Intel® Parallel Studio XE 2020 Composer Edition for Fortran Windows* Integration for Microsoft Visual Studio* 2019, Version 19.1.0055.16) - Visual studio 2019 (Microsoft Visual Studio Professional 2019, Version 16.4.5)
- compile options: /Od /warn:interfaces /module:"Debug\\" /object:"Debug\\" /Fd"Debug\vc160.pdb" /traceback /check:bounds /check:stack /libs:static /threads /Qmkl:sequential /c - linker options: /OUT:"Debug\Console13.exe" /INCREMENTAL:NO /NOLOGO /MANIFEST:NO /SUBSYSTEM:CONSOLE /IMPLIB:"C:\Users\mmpe\source\repos\Console13\Console13\Debug\Console13.lib"
Minimal example:
program Test use dfwin, only: loadlibrary implicit none print *, "rel path", loadlibrary('./tmp/tmp.dll')/=0 CALL DAXPY(3,[1d0,2d0,3d0],[2d0,2d0,2d0], 1, [3d0,3d0,3d0],1) print *, "abs path after daxpy", loadlibrary('C:/tmp/tmp.dll')/=0 print *, "rel path after daxpy", loadlibrary('./tmp/tmp.dll')/=0 end program
Output (multithreaded):
rel path T
abs path after daxpy T
rel path after daxpy F
Output (multithreaded dll):
rel path F
abs path after daxpy T
rel path after daxpy F
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I suspect that your execuitable's (at time of launch) current directory is not what you expect. Note, depending on how you launch the application, the current directory is not necessarily the same directory as that of the .exe.
I haven't tested this, you can experiment:
INQUIRE (DIRECTORY=dir, EXIST=ex [, DIRSPEC=dirspec] [, ERR=label] [, ID=id-var] [, IOMSG=msg-var] [, SIZE=sz] [, IOSTAT=i-var])
where you would use "." as the directory, you add a character variable dirspec of sufficient size (say 500 characters), and you supply the DIRSPEC= argument as well as additional arguments as you see fit.
Place the INQUIRE and PRINT *,dirspec before and after the call to DAXPY
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
What do you want? I often get the path of the exe from the command line args function and then use that as part of an absolute path. Windows has a complicated hierarchy of saving folder locations that varies dependant on windows version and the current phase of the moon.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The program shown is incorrect. The path string supplied to LoadLibrary should be NUL-terminated and should use backslashes. If it works at all it is accidental.
When a program is run from Visual Studio, the current directory is the one with the project folder, not the executable.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
andrew_4619 wrote:I often get the path of the exe from the command line args function
Under certain circumstances, that doesn't work. Use GetModuleFileName instead and GetLongPathName next if the executable has been launched by its short name.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you for your fast replies
I have modified the example program according to your suggestions, see below.
I set the working dir from visual studio: project settings - debugging - current working directory: c:\
Findings:
- The current working directory is c:\ both before and after DAXPY as expected
- Intel fortran 2019 update 5: relative path works
- Intel fortran 2020, Multithreaded: relative path works only before DAXPY
- Intel fortran 2020, Multithreaded DLL: relative path does not work
Example program
program Test use dfwin, only: loadlibrary implicit none character*255 dirspec LOGICAL ex INQUIRE (DIRECTORY='.', EXIST=ex, DIRSPEC=dirspec) print *, "CWD: ", trim(dirspec) print *, "rel path", loadlibrary('.\tmp\tmp.dll'//char(0))/=0 CALL DAXPY(3,[1d0,2d0,3d0],[2d0,2d0,2d0], 1, [3d0,3d0,3d0],1) INQUIRE (DIRECTORY='.', EXIST=ex, DIRSPEC=dirspec) print *, "CWD: ", trim(dirspec) print *, "abs path after daxpy", loadlibrary('C:\tmp\tmp.dll'//char(0))/=0 print *, "rel path after daxpy", loadlibrary('.\tmp\tmp.dll'//char(0))/=0 end program
Intel fortran 2019 update 5, Version 19.0.0052.16 (both "multithreaded" and "multithreaded dll")
CWD: C:\
rel path T
CWD: C:\
abs path after daxpy T
rel path after daxpy T
Intel fortran 2020, Version 19.1.0055.16
Multithreaded
CWD: C:\
rel path T
CWD: C:\
abs path after daxpy T
rel path after daxpy F
Multithreaded Dll
CWD: C:\
rel path F
CWD: C:\
abs path after daxpy T
rel path after daxpy F
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Call getlasterror after loadlibrary fails. The error code may help.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
getlasterror returns 0
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
So it's like DllMain returns false.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The write statement may reset the last error.
Try
iret=loadlibrary(...)
ierr=getlasterror()
write(...)... ret/=0,ierr
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You may call:
DWORD GetCurrentDirectory( DWORD nBufferLength, LPTSTR lpBuffer)
before and after DAXPY and LoadLibrary to see what is changed.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I cannot say this for certain, the return of False may be a case of "The specified library was not loaded... because it is already present".
IOW
Implementation 1: The specified library is loaded
Implementation 2: The load operation succeeded
These two results are only equivalent when the specified library was not present in memory when the function call was made.
Suggestions:
1) Save the return handle from LoadLibrary into a SAVE (or module) integer(handle) variable or array of said variables in the event you have multiple libraries you desire to control. Initialize these with 0 to indicate not loaded.
2) Test saved handle prior to LoadLibrary and use that in place of performing redundant load library
3) After step 2), use GetProcAddress to obtain (first time) or confirm (second and later) entry points to desired procedures.
4) When finished with a given library, issue FreeLibrary (and remember to zero out saved handle, and all saved procedure entry points for that library)
See: https://docs.microsoft.com/en-us/windows/win32/dlls/using-run-time-dynamic-linking
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@Luigi R: I was not able to call GetCurrentDirectory (In which module is it defined?). I have tried with both inquire as Jim suggest and with getcwd. In both cases the path is as expected and unchanged after DAXPY
@jimdempseyatthecove (Blackbelt): It is not related to opening the dll twice. It is the same if I invoke loadlibrary once after DAXPY
It seems to be related to visual studio in combination with intel fortran 2020 as it works when I compile from commandline with:
ifort test_rel_path.f90 /Qmkl:sequential /libs:static /fpp /list
I have attached the lst-files generated via cmd and VS.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page