gpt4 book ai didi

ctypes - 有没有办法确保我所有的 ctypes 都有 argtypes?

转载 作者:行者123 更新时间:2023-12-01 04:46:48 27 4
gpt4 key购买 nike

我知道我应该指定 argtypes对于我的 C/C++ 函数,因为我的某些调用会导致堆栈损坏。

    myCfunc.argtypes = [ct.c_void_p, ct.POINTER(ct.c_void_p)]
myCfunc.errcheck = my_error_check

事实上,我想确认我没有忘记为大约 100 个函数调用中的任何一个指定函数原型(prototype)( argtypes/ errcheck )......

现在我只是通过我的 Python 文件 grep 并在视觉上与包含原型(prototype)定义的文件进行比较。

有没有更好的方法来验证我是否定义了 argtypes/ errcheck我所有的电话?

最佳答案

@eryksun 提到的命名空间让我将 dll 包装在一个只公开显式注释函数的类中。只要 dll 没有函数名称“annotate”或“_error_check”(我没有),以下方法似乎对我有用:

import ctypes as ct

class MyWinDll:
def __init__(self, dll_filename):
self._dll = ct.WinDLL(dll_filename)
# Specify function prototypes using the annotate function
self.annotate(self._dll.myCfunc, [ct.POINTER(ct.c_void_p)], self._error_check)
self.annotate(self._dll.myCfunc2, [ct.c_void_p], self._error_check)
...

def annotate(self, function, argtypes, errcheck):
# note that "annotate" may not be used as a function name in the dll...
function.argtypes = argtypes
function.errcheck = errcheck
setattr(self, function.__name__, function)

def _error_check(self, result, func, arguments):
if result != 0:
raise Exception

if __name__ == '__main__':
dll = MyWinDll('myWinDll.dll')
handle = ct.c_void_p(None)
# Now call the dll functions using the wrapper object
dll.myCfunc(ct.byref(handle))
dll.myCfunc2(handle)

更新: @eryksun 的评论让我尝试通过让用户控制 WinDLL 来改进代码构造函数并尝试减少重复代码:
import ctypes as ct

DEFAULT = object()

def annotate(dll_object, function_name, argtypes, restype=DEFAULT, errcheck=DEFAULT):
function = getattr(dll_object._dll, function_name)
function.argtypes = argtypes
# restype and errcheck is optional in the function_prototypes list
if restype is DEFAULT:
restype = dll_object.default_restype
function.restype = restype
if errcheck is DEFAULT:
errcheck = dll_object.default_errcheck
function.errcheck = errcheck
setattr(dll_object, function_name, function)


class MyDll:
def __init__(self, ct_dll, **function_prototypes):
self._dll = ct_dll
for name, prototype in function_prototypes.items():
annotate(self, name, *prototype)


class OneDll(MyDll):
def __init__(self, ct_dll):
# set default values for function_prototypes
self.default_restype = ct.c_int
self.default_errcheck = self._error_check
function_prototypes = {
'myCfunc': [[ct.POINTER(ct.c_void_p)]],
'myCfunc2': [[ct.c_void_p]],
# ...
'myCgetErrTxt': [[ct.c_int, ct.c_char_p, ct.c_size_t], DEFAULT, None]
}
super().__init__(ct_dll, **function_prototypes)

# My error check function actually calls the dll, so I keep it here...
def _error_check(self, result, func, arguments):
msg = ct.create_string_buffer(255)
if result != 0:
raise Exception(self.myCgetErrTxt(result, msg, ct.sizeof(msg)))


if __name__ == '__main__':
ct_dll = ct.WinDLL('myWinDll.dll')
dll = OneDll(ct_dll)
handle = ct.c_void_p(None)
dll.myCfunc(ct.byref(handle))
dll.myCfunc2(handle)

(不知道要不要删掉原来的代码,留着供引用。)

关于ctypes - 有没有办法确保我所有的 ctypes 都有 argtypes?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46088164/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com