<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title><![CDATA[Approximatrix Forums — Incorrect working directory for DLL]]></title>
		<link>http://forums.approximatrix.com/viewtopic.php?id=938</link>
		<atom:link href="http://forums.approximatrix.com/extern.php?action=feed&amp;tid=938&amp;type=rss" rel="self" type="application/rss+xml" />
		<description><![CDATA[The most recent posts in Incorrect working directory for DLL.]]></description>
		<lastBuildDate>Tue, 27 Feb 2024 00:59:50 +0000</lastBuildDate>
		<generator>PunBB</generator>
		<item>
			<title><![CDATA[Re: Incorrect working directory for DLL]]></title>
			<link>http://forums.approximatrix.com/viewtopic.php?pid=4287#p4287</link>
			<description><![CDATA[<div class="quotebox"><cite>jeff wrote:</cite><blockquote><p>That&#039;s a tricky one.&nbsp; The working directory is not necessarily the directory where a DLL is located.&nbsp; It gets more complicated, though.&nbsp; The DLL&#039;s location is a bit difficult to determine from inside the DLL itself since these libraries can be loaded from anywhere, in theory.&nbsp; Getting the path of the executable is usually easier, but we can locate the DLL&#039;s path using a chain of Windows API calls.</p><p>We can use a combination of Windows calls to GetModuleHandleEx and GetModuleFileName to pull this off.&nbsp; Here&#039;s a module that wraps them nicely.</p></blockquote></div><p>Thanks a lot, Jeff god. It really works well.</p>]]></description>
			<author><![CDATA[null@example.com (Gale)]]></author>
			<pubDate>Tue, 27 Feb 2024 00:59:50 +0000</pubDate>
			<guid>http://forums.approximatrix.com/viewtopic.php?pid=4287#p4287</guid>
		</item>
		<item>
			<title><![CDATA[Re: Incorrect working directory for DLL]]></title>
			<link>http://forums.approximatrix.com/viewtopic.php?pid=4286#p4286</link>
			<description><![CDATA[<p>That&#039;s a tricky one.&nbsp; The working directory is not necessarily the directory where a DLL is located.&nbsp; It gets more complicated, though.&nbsp; The DLL&#039;s location is a bit difficult to determine from inside the DLL itself since these libraries can be loaded from anywhere, in theory.&nbsp; Getting the path of the executable is usually easier, but we can locate the DLL&#039;s path using a chain of Windows API calls.</p><p>We can use a combination of Windows calls to <a href="https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulehandleexa?redirectedfrom=MSDN">GetModuleHandleEx</a> and <a href="https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulefilenamea">GetModuleFileName</a> to pull this off.&nbsp; Here&#039;s a module that wraps them nicely:</p><div class="codebox"><pre><code>module dllpath

contains

    function get_dll_handle(justname) result(hModule)
    use iso_c_binding
    implicit none
    
        character(*), intent(in)::justname
        
        interface
            function GetModuleHandleEx(dwFlags, pModuleName, phModule) bind(c, name=&quot;GetModuleHandleExA&quot;)
                use iso_c_binding
                integer(kind=c_int32_t), value::dwFlags
                type(c_ptr), value::pModuleName
                type(c_ptr), value::phModule
                logical(kind=c_bool)::GetModuleHandleEx
            end function GetModuleHandleEx
        end interface
        
        character(kind=c_char, len=:), pointer::c_justname, c_fullpath
        type(c_ptr)::c_fullpath_loc
        type(c_ptr), target::hModule
        
        hModule = c_null_ptr
        
        allocate(character(len=len(justname)+1)::c_justname)
        
        c_justname = trim(justname)//c_null_char
        c_fullpath_loc = c_loc(c_fullpath)
        
        if(.not. GetModuleHandleEx(int(0, kind=c_int32_t), c_loc(c_justname), c_loc(hModule))) then
            Print *, &quot;ERROR: Could not retrieve module handle&quot;
            hModule = c_null_ptr
        end if
        
        deallocate(c_justname)
        
    end function get_dll_handle


    function get_module_path(hModule, fullpath)
    use iso_c_binding
    implicit none
        
        type(c_ptr), intent(in)::hModule
        character(*), intent(out)::fullpath
        logical::get_module_path
        integer::i
        
        interface
            function GetModuleFileName(hMod, pFilename, nSize) bind(c, name=&quot;GetModuleFileNameA&quot;)
                use iso_c_binding
                integer(kind=c_int32_t), value::nSize
                type(c_ptr), value::hMod, pFilename
                integer(kind=c_int32_t)::GetModuleFileName
            end function GetModuleFileName
        end interface
        
        character(kind=c_char, len=:), pointer::c_fullpath
        
        allocate(character(len=len(fullpath)+1)::c_fullpath)
        
        if(GetModuleFileName(hModule, c_loc(c_fullpath), len(fullpath)+1) == 0) then
            get_module_path = .false.
        else
            i = index(c_fullpath, c_null_char)
            fullpath = c_fullpath(1:i-1)
            get_module_path = .true.
        end if
        
        deallocate(c_fullpath)
        
    end function get_module_path

end module dllpath</code></pre></div><p>Things tend to be messy because we need to pass valid C strings into these procedures.&nbsp; I&#039;ve tried to isolate them, though.&nbsp; To use this in a routine, you would need first to use the proper modules:</p><div class="codebox"><pre><code>use dllpath
use iso_c_binding, only: c_ptr     ! Needed for holding a handle to our DLL</code></pre></div><p>Next, you need to declare some variables to fill in with values:</p><div class="codebox"><pre><code>    character(2048)::path    ! Probably long enough
    type(c_ptr)::hMod        ! A handle to our module</code></pre></div><p>And finally, to get the info, we first request the DLL handle using just the <em>base name of the DLL</em> and then pass the handle to the routine to get the path:</p><div class="codebox"><pre><code>    hMod = get_dll_handle(&quot;my_library.dll&quot;)
    if(.not. c_associated(hMod)) then
        Print *, &quot;no handle&quot;
    end if
    
    if(get_module_path(hMod, path)) then
        Print *, path
    else
        Print *, &quot;no path&quot;
    end if</code></pre></div><p>Again, it isn&#039;t a simple process because you need the operating system&#039;s help to determine where a DLL is located.</p>]]></description>
			<author><![CDATA[null@example.com (jeff)]]></author>
			<pubDate>Mon, 26 Feb 2024 13:24:25 +0000</pubDate>
			<guid>http://forums.approximatrix.com/viewtopic.php?pid=4286#p4286</guid>
		</item>
		<item>
			<title><![CDATA[Incorrect working directory for DLL]]></title>
			<link>http://forums.approximatrix.com/viewtopic.php?pid=4285#p4285</link>
			<description><![CDATA[<p>Hi everybody,</p><p>I have a DLL which is compiled with SF. But during the run of DLL, working directory from &quot;getcwd&quot; is not the same as the path where the DLL is. Are there any ways to return where the DLL file actually located?</p><p>Thanks.</p>]]></description>
			<author><![CDATA[null@example.com (Gale)]]></author>
			<pubDate>Mon, 26 Feb 2024 06:12:16 +0000</pubDate>
			<guid>http://forums.approximatrix.com/viewtopic.php?pid=4285#p4285</guid>
		</item>
	</channel>
</rss>
