【问题标题】:How do I allow NoneType Arguments OR a callback function to be passed to a function in ctypes如何允许将 NoneType 参数或回调函数传递给 ctypes 中的函数
【发布时间】:2021-06-20 11:41:57
【问题描述】:

我已经开始围绕一个 C/C++ 库编写一个非常简单的 Python 绑定,由于我没有权限,因此出于法律原因我无法在此分享。

这包含一个 WINFUNCTYPE() 作为回调,然后可以用来装饰一个函数以用作 python 中的回调,并在我绑定的函数的 argtypes 中定义。

这是代码中的样子:

from ctypes import *
from ctypes.wintypes import *

dll = WinDLL('path\\to\\dll')
callback = WINFUNCTYPE(None, POINTER(c_void_p), POINTER(LPBYTE), DWORD, c_ulonglong)
func = dll.FunctionImBinding
func.restype = POINTER(c_void_p)
func.argtypes = [LPCWSTR, callback, c_ulonglong, DWORD, DWORD]

然后我可以像这样使用它

@callback
def callback_func(*args):
    #Do something with args
    pass

func('string', callback_func, 0, 1, 2)

这很好,可以正常工作,没有问题。

当我这样做时,问题就来了:

func('string', None, 0, 1, 2)

我收到以下错误:

ctypes.ArgumentError: argument 2: <class 'TypeError'>: expected WinFunctionType instance instead of NoneType

这完全清楚为什么。 ctypes 期望将 WINFUNCTYPE() 视为第二个参数,而不是 NoneType,但在我使用的 SDK 的文档中,它指出将回调设置为 NULL 是可能的。但我只是不知道如何解决它,而且我很难在网上或 ctypes 文档中找到任何东西。

这是我第一次尝试绑定 C/C++ 库,如果我忽略了一些明显的东西,请原谅我。如果有人能帮我解决这个问题,我会非常感激。

【问题讨论】:

    标签: python c++ ctypes python-bindings


    【解决方案1】:

    你可以在创建回调时通过传递地址0给它一个空函数指针:

    func('string', callback(0), 0, 1, 2)
    

    事实上,我查看了 OP 发布的答案中的链接,稍后在线程中它具有基本相同的东西......将 None 转换为回调类型,例如cast(None, callback).

    【讨论】:

    • 谢谢,我更喜欢这个
    【解决方案2】:

    好的,我在这里找到了解决方案https://ctypes-users.narkive.com/wmJNDPu2/optional-callbacks-passing-null-for-function-pointers

    将澄清我在这里所做的而不是删除问题。

    定义一个自定义的 from_param 并使用这样的 classmethod 在回调中设置它。

    from ctypes import _CFuncPtr
    
    def from_param(cls, obj):
        if obj is None:
            return None
        return _CFuncPtr.from_param(obj)
    
    callback.from_param = classmethod(from_param)
    

    【讨论】:

      猜你喜欢
      • 2015-09-05
      • 2013-02-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-25
      • 1970-01-01
      相关资源
      最近更新 更多