question on callback functions with ctypes
oyster
lepto.python at gmail.com
Sun Jun 21 01:08:14 EDT 2020
question on callback functions with ctypes
I try to use GoVCL( https://github.com/ying32/govcl ) in python via
ctypes. GoVCL supplies C header and simple C demo under
https://github.com/ying32/govcl/tree/master/Tools/makeCHeader/test
Now the simple python code can run on both win7 and win10 according to
Eryk Sun's suggestion - thank you Eryk Sun. But I am still puzzled by
2 questions
1. the callback function does not been invoked, so there must be
something wrong when I deal with it. However, I can't figure it out.
2. in the original main.c, there is no need to call
`vcl.SetEventCallback(doEventCallbackProc)`. But I learn this in a
python code that uses cffi to call GoVCL. How can I make the python
code as simple as the C code?
Thanks
The following python code is a simplified version of the C code
```python
import sys, os
import ctypes
# In Python 3.8+, ctypes no longer searches PATH or the
# current working directory when loading DLLs.
liblcl_path = os.path.join(os.path.split(os.path.realpath(__file__))[0],
'liblcl.dll')
vcl = ctypes.CDLL(liblcl_path)
def _doEventCallbackProc(f, args, argcount):
print(f, args, argcount)
if f == ctypes.addressof(onButton1Click):
vcl.DShowMessage("Hello world!".encode('utf8'))
elif f == ctypes.addressof(onFormKeyDown):
fnOnFormKeyDown(f, args, argcount)
elif f == ctypes.addressof(onFormKeyDown):
fnOnFormKeyDown(f, args, argcount)
doEventCallbackProc = ctypes.CFUNCTYPE(ctypes.c_void_p,
ctypes.c_void_p, ctypes.c_void_p, ctypes.c_long)(_doEventCallbackProc)
def _onButton1Click(sender):
vcl.ShowMessage("Hello world!");
onButton1Click = ctypes.CFUNCTYPE(None, ctypes.c_void_p)(_onButton1Click)
print(ctypes.addressof(onButton1Click))
Char = ctypes.c_uint16
TShiftState = ctypes.c_uint32
def _onFormKeyDown(sender, key, shift):
print(key, shift);
onFormKeyDown = ctypes.CFUNCTYPE(None, ctypes.c_void_p,
ctypes.POINTER(Char), TShiftState)(_onFormKeyDown)
print(ctypes.addressof(onFormKeyDown))
def _onEditChange(sender):
print("%s\n", vcl.Edit_GetText(sender));
onEditChange = ctypes.CFUNCTYPE(None, ctypes.c_void_p)(_onEditChange)
print(ctypes.addressof(onEditChange))
def main():
vcl.SetEventCallback(doEventCallbackProc)
vcl.Application_Instance.restype = ctypes.c_void_p
Application = vcl.Application_Instance()
vcl.Application_Initialize.argtypes = ctypes.c_void_p,
vcl.Application_Initialize(Application)
vcl.Application_CreateForm.argtypes = ctypes.c_void_p, ctypes.c_bool
vcl.Application_CreateForm.restype = ctypes.c_void_p
form = vcl.Application_CreateForm(Application, False);
vcl.Form_SetCaption.argtypes = ctypes.c_void_p, ctypes.c_char_p
vcl.Form_SetCaption(form, "LCL Form".encode('utf8'));
vcl.Form_SetKeyPreview.argtypes = ctypes.c_void_p, ctypes.c_bool
vcl.Form_SetKeyPreview(form, True);
vcl.Form_SetOnKeyDown.argtypes = ctypes.c_void_p,
ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.POINTER(Char),
TShiftState)
vcl.Form_SetOnKeyDown(form, onFormKeyDown);
vcl.Button_Create.argtypes = ctypes.c_void_p,
vcl.Button_Create.restype = ctypes.c_void_p
btn = vcl.Button_Create(form);
vcl.Button_SetParent.argtypes = ctypes.c_void_p, ctypes.c_void_p
vcl.Button_SetParent(btn, form);
vcl.Button_SetOnClick.argtypes = ctypes.c_void_p,
ctypes.CFUNCTYPE(None, ctypes.c_void_p)
vcl.Button_SetOnClick(btn, onButton1Click);
vcl.Button_SetCaption.argtypes = ctypes.c_void_p, ctypes.c_char_p
vcl.Button_SetCaption(btn, "button1".encode('utf8'));
vcl.Button_SetLeft.argtypes = ctypes.c_void_p, ctypes.c_uint32
vcl.Button_SetLeft(btn, 100);
vcl.Button_SetTop.argtypes = ctypes.c_void_p, ctypes.c_uint32
vcl.Button_SetTop(btn, 100);
vcl.Edit_Create.argtypes = ctypes.c_void_p,
vcl.Edit_Create.restype = ctypes.c_void_p
edit = vcl.Edit_Create(form);
vcl.Edit_SetParent.argtypes = ctypes.c_void_p, ctypes.c_void_p
vcl.Edit_SetParent(edit, form);
vcl.Edit_SetOnChange.argtypes = ctypes.c_void_p,
ctypes.CFUNCTYPE(None, ctypes.c_void_p)
vcl.Edit_SetOnChange(edit, onEditChange);
vcl.Application_Run.argtypes = ctypes.c_void_p,
vcl.Application_Run(Application);
main()
```
the C code
```C
#include "liblcl.h"
#ifdef _WIN32
char *UTF8Decode(char* str) {
int len = MultiByteToWideChar(CP_UTF8, 0, str, -1, 0, 0);
wchar_t* wCharBuffer = (wchar_t*)malloc(len * sizeof(wchar_t) + 1);
MultiByteToWideChar(CP_UTF8, 0, str, -1, wCharBuffer, len);
len = WideCharToMultiByte(CP_ACP, 0, wCharBuffer, -1, 0, 0, 0, NULL);
char* aCharBuffer = (char*)malloc(len * sizeof(char) + 1);
WideCharToMultiByte(CP_ACP, 0, wCharBuffer, -1, aCharBuffer, len, 0, NULL);
free((void*)wCharBuffer);
return aCharBuffer;
}
#endif
void onButton1Click(TObject sender) {
ShowMessage("Hello world!");
}
void onOnDropFiles(TObject sender, void* aFileNames, intptr_t len) {
printf("aFileNames: %p, len=%d\n", aFileNames, len);
intptr_t i;
for (i = 0; i < len; i++) {
#ifdef _WIN32
char *filename = UTF8Decode(GetStringArrOf(aFileNames, i));
#else
char *filename = GetStringArrOf(aFileNames, i);
#endif
printf("file[%d]=%s\n", i+1, filename);
#ifdef _WIN32
free((void*)filename);
#endif
}
}
void onFormKeyDown(TObject sender, Char* key, TShiftState shift) {
printf("key=%d, shift=%d\n", *key, shift);
if (*key == vkReturn) {
ShowMessage("press Enter!");
}
TShiftState s = Include(0, ssAlt);
if (InSet(s, ssAlt)) {
printf("ssAlt1\n");
}
s = Exclude(s, ssAlt);
if (!InSet(s, ssAlt)) {
printf("ssAlt2\n");
}
}
void onEditChange(TObject sender) {
printf("%s\n", Edit_GetText(sender));
}
int main()
{
#ifdef _WIN32
if (load_liblcl("liblcl.dll")) {
#endif
#ifdef __linux__
if (load_liblcl("liblcl.so")) {
#endif
#ifdef __APPLE__
if (load_liblcl("liblcl.dylib")) {
#endif
Application_Initialize(Application);
TForm form = Application_CreateForm(Application, FALSE);
Form_SetCaption(form, "LCL Form");
Form_SetPosition(form, poScreenCenter);
Form_SetAllowDropFiles(form, TRUE);
Form_SetOnDropFiles(form, onOnDropFiles);
Form_SetKeyPreview(form, TRUE);
Form_SetOnKeyDown(form, onFormKeyDown);
TButton btn = Button_Create(form);
Button_SetParent(btn, form);
Button_SetOnClick(btn, onButton1Click);
Button_SetCaption(btn, "button1");
Button_SetLeft(btn, 100);
Button_SetTop(btn, 100);
TEdit edit = Edit_Create(form);
Edit_SetParent(edit, form);
Edit_SetLeft(edit, 10);
Edit_SetTop(edit, 10);
Edit_SetOnChange(edit, onEditChange);
Application_Run(Application);
close_liblcl();
}
return 0;
}
```
More information about the Python-list
mailing list