Using Ctypes To Load A Specific Runtime Library (msvcrt80)
We're using ctypes.windll to load a third-party library. This library uses 'MSVCRT80' and states that it's callers responsibility to free resources. Therefor we've tried using wind
Solution 1:
According to Hans' comment in your other question, you can use GetModuleHandle to get the handle to the already loaded CRT. Like this:
handle = windll.kernel32.GetModuleHandleA('msvcr80')
msvcr80 = WinDLL('', handle=handle)
msvcr80.free(...)
For what it's worth, windll.msvcrt
actually refers to the Windows system supplied C runtime, which is named msvcrt.dll
and resides in your system32
directory.
Solution 2:
I finally figured out a workaround for this problem. After loading the external library, I enumerate over the loaded modules using EnumProcessModules
, determine the filenames using GetModuleFileName
and reference the correct module and load the free()
-function from this runtime.
The code I'm using to do this is as follows:
from ctypes import *
defenumProcessModules():
# Get handle of current process
kernel32 = windll.kernel32
kernel32.GetCurrentProcess.restype = c_void_p
hProcess = kernel32.GetCurrentProcess()
# Load EnumProcessModules either from kernel32.dll or psapi.dll try:
EnumProcessModulesProc = windll.psapi.EnumProcessModules
except AttributeError:
EnumProcessModulesProc = windll.kernel32.EnumProcessModules
EnumProcessModulesProc.restype = c_bool
EnumProcessModulesProc.argtypes = [c_void_p, POINTER(c_void_p), c_ulong, POINTER(c_ulong)]
hProcess = kernel32.GetCurrentProcess()
hMods = (c_void_p * 1024)()
cbNeeded = c_ulong()
if EnumProcessModulesProc(hProcess, hMods, sizeof(hMods), byref(cbNeeded)):
return hMods
returnNonedefgetLoadedModule(moduleName):
kernel32 = windll.kernel32
kernel32.GetModuleFileNameA.restype = c_ulong
kernel32.GetModuleFileNameA.argtypes = [c_void_p, c_char_p, c_ulong]
modules = enumProcessModules()
if modules isNone:
returnNonefor module in modules:
cPath = c_char_p(' ' * 1024)
kernel32.GetModuleFileNameA(module, cPath, c_ulong(1024))
path = cPath.value
if path.lower().endswith(moduleName):
return module
returnNone
To load the correct runtime and find the free()
function I use the code above:
runtimeModuleHandle = getLoadedModule("msvcr80.dll")
runtimeModule = ctypes.CDLL('', handle = runtimeModuleHandle) # cdecl calling conventionruntimeModule.free.restype = None
runtimeModule.free.argtypes = [ctypes.c_void_p]
myFreeProc = runtimeModule.free
Post a Comment for "Using Ctypes To Load A Specific Runtime Library (msvcrt80)"