使用ctypes动态设置CDLL中任意函数restype失败的解决方法咨询
使用ctypes动态设置CDLL中任意函数restype失败的解决方法咨询
你遇到的这个问题其实是ctypes的一个特性导致的:当你用mydll['函数名']这种索引方式访问DLL函数时,每次都会返回一个全新的函数对象。这意味着你前一次给它设置的restype会被直接丢弃,下一次通过索引调用时,拿到的又是默认返回ctypes.c_long的新对象,自然就取不到正确的字符串结果了。而用属性访问(mydll.函数名)的方式时,ctypes会缓存这个函数对象,所以你设置的restype能一直生效。
解决这个问题的核心思路是:先把函数对象存储到一个变量里,再对这个变量配置restype和argtypes,之后始终通过这个变量调用函数,避免每次都从DLL索引中获取新对象。
基础解决写法
直接修改你的代码,先把函数对象存下来:
import ctypes mydll = ctypes.CDLL(libName) # 先将函数对象赋值给变量 target_func = mydll['GET_LAST_MESSAGE'] # 对变量进行配置 target_func.argtypes = None target_func.restype = ctypes.c_char_p # 通过变量调用函数 message = target_func()
类封装的进阶方案
考虑到你需要封装一个类来处理任意函数的加载,我们可以加入缓存机制,把已经配置好的函数对象存起来,避免重复创建和配置:
import ctypes class DLLHandler: def __init__(self, lib_name): self.dll = ctypes.CDLL(lib_name) # 用字典缓存已配置的函数对象 self._cached_functions = {} def get_function(self, func_name, restype=None, argtypes=None): # 如果函数未缓存,就创建并配置 if func_name not in self._cached_functions: func = self.dll[func_name] if argtypes is not None: func.argtypes = argtypes if restype is not None: func.restype = restype self._cached_functions[func_name] = func # 返回缓存的函数对象 return self._cached_functions[func_name] # 使用示例 handler = DLLHandler(libName) # 获取并配置指定函数 get_last_msg = handler.get_function('GET_LAST_MESSAGE', restype=ctypes.c_char_p) # 调用函数 message = get_last_msg()
这样无论你动态传入什么函数名,都能确保配置的restype和argtypes不会丢失,完美适配类封装的需求。
备注:内容来源于stack exchange,提问作者Victor
相关产品推荐
相关产品推荐

