- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I am able to call SetDllDirectory using the following code (found on your web https://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/topic/291698):
INTERFACE
FUNCTION SetDllDirectory(lpPathName)
IMPORT
LOGICAL(KIND=1) :: SetDllDirectory
!DEC$ ATTRIBUTES DEFAULT, STDCALL, DECORATE, ALIAS:'SetDllDirectoryA' :: SetDllDirectory
!DEC$ ATTRIBUTES REFERENCE, ALLOW_NULL :: lpPathName
!
CHARACTER(LEN=*) lpPathName ! LPCSTR lpPathName
END FUNCTION
END INTERFACE
I am curious, why the function is called SetDllDirectoryA in the Alias? What is the extra A?
Now I want to use BIND(C) to do the same, but it does not work. Here is my example, but it results into link error for SetDllDirectoryA
INTERFACE
FUNCTION SetDllDirectory(lpPathName), BIN(C, name='SetDllDirectoryA')
IMPORT
LOGICAL(KIND=1) :: SetDllDirectory
CHARACTER(KIND=C_CHAR), DIMENSION(*), INTENT(IN) :: lpPathName
!
END FUNCTION
END INTERFACE
The USE, INTRINSIC :: ISO_C_BINDING
statement is placed in my main module declaring this interface.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The Win32 API provides two versions of any API taking a character string - a "wide" unicode (UTF-16) variant suffixed with W and an "ansi" variant, details of which are dependent on the code page in use, suffixed with 'A'.
On 32 bit windows, the Windows API's use the STDCALL calling convention. This calling convention is not typically used by 32 bit Windows C compilers of today. BIND(C), without other Fortran compiler specific directives, specifies "compatible with [some specified] C compiler". The linker names for a certain procedure name generated by the two different calling conventions are [thankfully] different, hence you see the error.
Later versions of ifort let you mix BIND(C) and the !DEC$ ATTRIBUTES STDCALL specification, earlier versions do not.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks
So the conclusion is that in this case I should stay with the given code and not try to use BIND(C)... Which is disappointing since it means that we are still unable to eliminate the strange looking !DEC$ directives.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
google msdn SetDllDirectory and you will find the ref page for that sdk routine
https://msdn.microsoft.com/en-us/library/windows/desktop/ms686203(v=vs.85).aspx
I will also note that the function is type BOOL so integer(kind=4) is your nearest equivalent. or USE IFWINTY and then have INTEGER(BOOL)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks
I know how to use it in C, and the code shown in my first question works in Fortran. I was just curious if I can make it work with BIND(C,...).
Apparently it is not possible. This is an essential function that does not exist in Fortran, from what I know.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
jean wrote:
Thanks
I know how to use it in C, and the code shown in my first question works in Fortran. I was just curious if I can make it work with BIND(C,...).
Apparently it is not possible. This is an essential function that does not exist in Fortran, from what I know.
As IanH mentioned in message #2, you can use BIND(C), however you still need the STDCALL attribute because of the way Microsoft Windows API are set up. And if you're using a newer version, say current compiler 16, of Intel Fortran, BIND(C) and STDCALL can be used together.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
jean wrote:
Thanks
So the conclusion is that in this case I should stay with the given code and not try to use BIND(C)... Which is disappointing since it means that we are still unable to eliminate the strange looking !DEC$ directives.
Not unless you want to restrict yourself to 64 bit windows. On 64 bit windows the STDCALL API calling convention is different, and is commonly the same as the calling convention of a C compiler.
On 32 bit windows this issue is not Fortran language specific (though it may vary from compiler to compiler) - for example C code typically requires something equivalent to the strange looking __stdcall declaration specifier in the declaration of the function..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Unfortunately you can't use a compiler switch to make the default C compiler in interface blocks the one that you get if you use !DEC$ ATTRIBUTES STDCALL. Example of BIND(C) interface body that works:
module M use ifwin use ISO_C_BINDING implicit none private public SetDllDirectory interface function SetDllDirectory(lpPathName) bind(C,name='SetDllDirectoryA') import implicit none !DEC$ ATTRIBUTES STDCALL :: SetDllDirectory integer(BOOL) SetDllDirectory character(kind=C_CHAR), intent(in), dimension(*) :: lpPathName end function SetDllDirectory end interface end module M program P use M use ISO_C_BINDING implicit none character(kind=C_CHAR), pointer :: lpPathName(:) integer R call C_F_POINTER(C_NULL_PTR,lpPathName,[0]) R = SetDllDirectory(lpPathName) write(*,'(*(g0))') 'Result = ',R end program P
Reading the documentation, any nonzero return value is indicative of successful execution of SetDllDirectory. In particular if you use LOGICAL(1) as your result type and the result is 256, your program will see an unsuccessful result erroneously. Also is /fpscomp:nologicals is in effect and the result is 2, your program will again see an unsuccessful result erroneously. Don't mix Fortran LOGICAL variables with any kind of C object and don't use the wrong size variables in interfacing.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks, I will try your code.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I need help with another issue on DLLs.
The above call of SetDllDirectory is apparently adding a new path, but removing the previously added search path. So I presume I need to use the call to AddDllDirectory and then use LoadLibraryEx. I am wondering if there is an easier way to add DLL search paths in Fortran. If not, do you have an example of usage for the two above functions?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
jean wrote:
I need help with another issue on DLLs.
The above call of SetDllDirectory is apparently adding a new path, but removing the previously added search path. So I presume I need to use the call to AddDllDirectory and then use LoadLibraryEx. I am wondering if there is an easier way to add DLL search paths in Fortran. If not, do you have an example of usage for the two above functions?
How the Microsoft Windows API work should be the same whether the calls are made in Fortran or C, C++, etc.. So your statement, "I am wondering if there is an easier way to add DLL search paths in Fortran", doesn't make much sense. Earlier you said "I know how to use it in C", well put together some C code that does what you want using Microsoft APIs and post it here - some reader here will surely be able to show you how to do the same in Fortran.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks, you are absolutely correct. I did that, but I was curious about Fortran with the new features.
Thanks again.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
jean wrote:
.. I did that, but I was curious about Fortran with the new features. ..
By "I did that", I assume you mean you have called Windows APIs from C and you understand how those functions work. Do you find "call of SetDllDirectory" (you said it is "apparently adding a new path, but removing the previously added search path") any different in Fortran versus C?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The call above was made from Fortran to C so it works exactly like in C. I did not realize at the beginning how it was behaving exactly.
The issue is that it is not possible to do these things directly from Fortran. For example loadlibrary works, getprocaddress works and also loadlibraryEx, but not AddDllDirectory . In fact the working functions are not documented in the Help of Intel, so I was wondering if there are some other functions to do the same things. Calling C is an option, but why we do not have these features in Fortran directly...
Thanks for all the answers.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
AddDLLDirectory is a relatively recent addition to the Windows API. It won't work on Windows 7, for example, unless you have particular updates installed. The definitions for some of these recent API's (and for some that are not so recent) are simply yet to be added to the IFWIN style modules. It is the same situation as if you are programming in C and using an older version of the Windows SDK - you won't have these API's in the Windows header files.
But LoadLibrary and the like have been around ever since Windows NT.
But it is easy enough to write your own version of the interface, as seen upthread.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page