I've started writing a very simple Python binding around a C/C++ library, which I can't share here for legal reasons as I don't have permission.
This contains a WINFUNCTYPE() as a callback, which can then be used to decorate a function to use as the callback in python, and is defined in the argtypes of my function that I'm binding.
Here is what this looks like in code:
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]
I can then use that like this
@callback
def callback_func(*args):
#Do something with args
pass
func('string', callback_func, 0, 1, 2)
This is fine, and works as expected with no problems.
The problem comes when I do something like this:
func('string', None, 0, 1, 2)
I get the following error:
ctypes.ArgumentError: argument 2: <class 'TypeError'>: expected WinFunctionType instance instead of NoneType
Which is completely clear why. ctypes is expecting to see a WINFUNCTYPE() as the second argument and not NoneType, but in the documentation for the SDK I'm using it states the setting the callback as NULL is possible. But I just don't know how to fix it, and I'm struggling to find anything online or in the ctypes docs.
This is the first time I've tried binding a C/C++ library so forgive me if I'm overlooking something obvious. If anyone can help me solve this I would be really greatful.
You can give it a null function pointer by passing address 0 when creating the callback:
func('string', callback(0), 0, 1, 2)
In fact I looked at the link in the OP's posted answer and later in the thread it has basically the same thing...cast None to the callback type, e.g. cast(None, callback)
.