Freddie Witherden
Freddie Witherden

Reputation: 2426

Loading Temporary DLLs into Python on Win32

A common idiom I have seen in various Python code bases to dynamically generate/load a C function at runtime is:

import tempfile
import shutil
from ctypes import CDLL

workdir = tempfile.mkdtemp()
try:
    # Generate and write code in workdir
    # ...
    # Compile and link into an .so/.dylib/.dll
    # ...
    lib = CDLL(path_to_lib)
finally:
    shutil.rmtree(workdir)

While this appears to work quite nicely on *nix systems I am unsure how well it will work on Win32. This is because, in my experience, when the .dll inside the temporary directory is mapped into the process it is not possible to unlink it. Hence, rmtree will fail.

What options are available to me to ensure that on Win32 the .dll (and the directory in which it resides) are deleted ASAP (so as soon as the underlying lib has been gc'ed or when the application terminates so as not to leave temporary cruft about).

Upvotes: 4

Views: 371

Answers (1)

Eryk Sun
Eryk Sun

Reputation: 34270

Use the Kernel32 function FreeLibrary to unmap the DLL and decrement its reference count. To get the handle you can use GetModuleHandleW, but it's already available in the _handle attribute.

Edit: The underlying _ctypes module already provides this function as well as dlclose for POSIX. If there's an error these functions raise WindowsError / OSError.

>>> import os                               
>>> from ctypes import *  
>>> from _ctypes import FreeLibrary

>>> lib = CDLL('./lib.dll')
>>> hlib = lib._handle
>>> del lib
>>> FreeLibrary(hlib)

>>> os.remove('./lib.dll')
>>> os.path.exists('./lib.dll')
False

Upvotes: 2

Related Questions