dllfix

If you're making a Starkit for a Windows machine, and your Starkit includes a binary module, and the DLL for that binary module relies on one or more other DLLs (i.e. external dependencies to your packaged library), then you've probably discovered that Starkit itself won't put those extra DLLs in a place where Windows can find them.

This package solves that problem. It copies any DLLs you specify out into a temporary directory and adds that directory to the DLL search path.

This is how you use it:

::dllfix::setup name source-dll-directory list-of-dlls

The "name" argument is used as the prefix for the temporary directory. The source dll directory is a path to where the DLLs are stored. The list of dlls is a list of dlls.

If you feel like removing the temp directory and DLLs when you're done, you can call ::dllfix::cleanup to do so.

Enjoy!

st3ve


#
# Copy dependent dlls out to env(temp) and use ffidl to set them to load
# first in the DLL search path
#
package require ffidl

ffidl::callout add_dir_to_dll_search_path {pointer-utf8} int [ffidl::symbol kernel32.dll SetDllDirectoryA]



namespace eval ::dllfix {
  namespace export setup cleanup

  set dlls {}
  set dllpath {}
}


#
# takes a source and a list of DLLs to copy
#
proc ::dllfix::setup { name src dll_list } {

   global env
   variable dlls
   variable dllpath

   # make a probably-unique temp directory for the dlls
   set dllpath [file join $env(temp) $name-[clock seconds]]
   if { [catch {file mkdir $dllpath} err] } {
      return $err
   }

   # copy the DLLs
   foreach dll $dll_list {

      # try to copy ..
      if { [catch {file copy -force [file join $src $dll] $dllpath} err] } {

         # error?  clean up any already-copied DLLs and return the error
         ::dllfix::cleanup
         return $err

      }

      # copied?  append to the cleanup list
      lappend dlls $dll

   }

   # and add the dll path to the search path
   add_dir_to_dll_search_path $dllpath

}


#
# remove any DLLs we've copied into env(temp)
#
proc ::dllfix::cleanup {} {

   variable dlls
   variable dllpath

   # remove ..
   file delete $dllpath

   # and empty the list
   set dlls {}

}

package provide dllfix [lindex {Revision: 0.1} 1]