Jul-11-2020, 09:02 AM
Hi, I met a case in which NULL can be used as a C function's parameter which is actually a pointer function. I can't finger out how to do it, can anyone help. Thanks
1. the case
The C function in [LCUI](https://github.com/lc-soft/LCUI) is defined as
2. the 1st attempt
1. the case
The C function in [LCUI](https://github.com/lc-soft/LCUI) is defined as
typedef void(*LCUI_WidgetEventFunc)(LCUI_Widget, LCUI_WidgetEvent, void*); LCUI_API int Widget_BindEvent(LCUI_Widget widget, const char *event_name, LCUI_WidgetEventFunc func, void *data, void(*destroy_data)(void*));which is called in [helloworld](https://github.com/lc-soft/LCUI/blob/dev...orld.c#L31) as
static void OnBtnClick(LCUI_Widget self, LCUI_WidgetEvent e, void *arg){ do something(); } Widget_BindEvent(btn, "click", OnBtnClick, NULL, NULL);Then I try to translate it into python
2. the 1st attempt
LCUI_WidgetEventFunc = ctypes.CFUNCTYPE(None, LCUI_Widget, LCUI_WidgetEvent, ctypes.c_void_p) _Widget_BindEvent = dll.Widget_BindEvent #~ _Widget_BindEvent.argtypes = LCUI_Widget, ctypes.c_char_p, LCUI_WidgetEventFunc, ctypes.c_void_p, ctypes.c_void_p def Widget_BindEvent( widget, event_name, func, data, destroy_data,): event_name = event_name.encode('utf8') func = LCUI_WidgetEventFunc(func) return _Widget_BindEvent( widget, event_name, func, data, destroy_data)then I call it as
def OnBtnClick(self, e, arg): do something() Widget_BindEvent( btn, "click", LCUI_WidgetEventFunc(OnBtnClick), None, ctypes.cast(None, ctypes.CFUNCTYPE(None, ctypes.c_void_p)) );But python fails to run this code and says
Output:Traceback (most recent call last):
File "helloworld.py", line 60, in <module>
main()
File "helloworld.py", line 54, in main
ctypes.cast(None, ctypes.CFUNCTYPE(None, ctypes.c_void_p))
File "r:\lc\LCUI.py", line 88, in Widget_BindEvent
destroy_data
OSError: exception: access violation reading 0x0000000000000270
3. the 2nd try_Widget_BindEvent = dll.Widget_BindEvent prototype = ctypes.CFUNCTYPE(ctypes.c_int, LCUI_Widget, ctypes.c_char_p, LCUI_WidgetEventFunc, ctypes.c_void_p, ctypes.CFUNCTYPE(None, ctypes.c_void_p) ) Widget_BindEvent = prototype(_Widget_BindEvent) Widget_BindEvent( btn, "click".encode(), LCUI_WidgetEventFunc(OnBtnClick), None, ctypes.cast(None, ctypes.CFUNCTYPE(None, ctypes.c_void_p)) );this time python runs the code but says
Output:Traceback (most recent call last):
File "_ctypes/callbacks.c", line 234, in 'calling callback function'
OSError: exception: access violation reading 0x0000000000000270
So what is the proper way to wrap Widget_BindEvent so that we can use real function or NULL in it?