使用ctypes加载特定的运行时库(MSVCRT80) [英] Using ctypes to load a specific runtime library (MSVCRT80)

查看:147
本文介绍了使用ctypes加载特定的运行时库(MSVCRT80)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正在使用 ctypes.windll 加载第三方库。该库使用 MSVCRT80,并声明调用者有责任释放资源。因此,我们尝试使用 windll.msvcrt.free(pointer)释放外部库返回的资源。这失败了,因为 windll.msvcrt 是另一个运行时(Python与之链接的 MSVCRT90.DLL)

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 windll.msvcrt.free(pointer) to free resources returned by the external library. This fails as windll.msvcrt is another runtime ('MSVCRT90.DLL' which Python is linked with)

因此我们明确需要加载 MSVCRT80.DLL,但我找不到加载该库的方法。我尝试使用 ctypes.util.find_library(’msvcrt80'),但是返回 None 。我猜这是因为此函数仅通过路径查找,而实际库位于 c:\windows\winsxs\amd64_microsoft.vc80.crt_1fc8b3b9a1e18e3b_8.0.50727.6195_none_88e41e092fab0294

Therefor we explicitly need to load 'MSVCRT80.DLL', but I can't find a way to load this library. I've tried using ctypes.util.find_library('msvcrt80') but this returns None. I guess this is because this function only looks through the path, while the actual library is located at c:\windows\winsxs\amd64_microsoft.vc80.crt_1fc8b3b9a1e18e3b_8.0.50727.6195_none_88e41e092fab0294.

有什么方法可以使用 ctypes 加载正确的运行时吗?

Is there any way I can load the correct runtime using ctypes?

推荐答案

我终于找到解决该问题的方法。加载外部库后,我使用 EnumProcessModules 枚举已加载的模块,使用 GetModuleFileName 确定文件名并引用正确的模块并从此运行时加载 free()函数。

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 *

def enumProcessModules():   
    # 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
    return None

def getLoadedModule(moduleName):     
    kernel32 = windll.kernel32
    kernel32.GetModuleFileNameA.restype = c_ulong
    kernel32.GetModuleFileNameA.argtypes = [c_void_p, c_char_p, c_ulong]

    modules = enumProcessModules()
    if modules is None:
        return None    
    for 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
    return None

要加载正确的运行时并找到 free()函数,我使用t上面的代码:

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 convention
    runtimeModule.free.restype = None
    runtimeModule.free.argtypes = [ctypes.c_void_p]        
    myFreeProc = runtimeModule.free

这篇关于使用ctypes加载特定的运行时库(MSVCRT80)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆