question on callback functions with ctypes

2020-06-20 Thread oyster
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", aFileN

Re: how to let argument be optional falling back to certain integer

2020-06-20 Thread Chris Angelico
On Sun, Jun 21, 2020 at 10:06 AM Boris Dorestand  wrote:
>
> Chris Angelico  writes:
> > Zero being false shouldn't be a surprise. If None can count as false,
> > then so should other "emptiness" values. (Remember, the canonical
> > falseness value is False, not None.)
>
> This is true.  I have written 0 as false in C so many times.  But
> clearly for me times have changed...  I now look at numbers as a thing
> in their own special class not to be confused as truth-values.  (So much
> so that I fell for this.)  But I confess I still think of numbers as all
> TRUE.  (Even zero!)

That's an interesting view. But fortunately you can have that too -
just have to treat None as its own thing, instead of using a falsiness
test. :)

> Anyway, I kind of replied just to thank you all for the great group this
> is.  ChrisA, I don't know how can keep up with this newsgroup, but you
> do.  This is crazy.  Years go by and when I come back, there you are
> still.  You're priceless.

You're most welcome! I hang out here a lot because the people here are
awesome. I've learned a lot, helped a lot of people, the language has
shifted, it's been great.

I like to think of myself as an empowerer - I help YOU to be able to
do amazing things. It's you who are the awesome creative person who's
making code do magic, and I'm just removing barriers from your way :)

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: how to let argument be optional falling back to certain integer

2020-06-20 Thread Boris Dorestand
Chris Angelico  writes:

> On Sun, Jun 21, 2020 at 2:02 AM Boris Dorestand  
> wrote:
>>
>> I just wrote
>>
>> def f(y, N, k = None):
>>   k = k or (N - 1)
>>   return k
>>
>> I was surprised to find out that 0 == False, so f(7, 31, 0) produces 31.
>>
>> I'd like 0 to be a valid choice for k.
>>
>> How do you guys let k be an optional argument such that it defaults to
>> N - 1?
>>
>
> The easiest way is to explicitly check for None.
>
> if k is None: k = N - 1

Got it.  That's clear code.

> Zero being false shouldn't be a surprise. If None can count as false,
> then so should other "emptiness" values. (Remember, the canonical
> falseness value is False, not None.)

This is true.  I have written 0 as false in C so many times.  But
clearly for me times have changed...  I now look at numbers as a thing
in their own special class not to be confused as truth-values.  (So much
so that I fell for this.)  But I confess I still think of numbers as all
TRUE.  (Even zero!)

Anyway, I kind of replied just to thank you all for the great group this
is.  ChrisA, I don't know how can keep up with this newsgroup, but you
do.  This is crazy.  Years go by and when I come back, there you are
still.  You're priceless.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: how to let argument be optional falling back to certain integer

2020-06-20 Thread Python

Le 20/06/2020 à 18:23, Stefan Ram a écrit :

Boris Dorestand  writes:

def f(y, N, k = None):
  k = k or (N - 1)
  return k
I was surprised to find out that 0 == False, so f(7, 31, 0) produces 31.


   bool is a subtype of int.


I'd like 0 to be a valid choice for k.


k = N-1 if k==None else k


When comparing wih None "is" is preferred to ==

k = N - 1 if k is None else k
--
https://mail.python.org/mailman/listinfo/python-list


Re: how to let argument be optional falling back to certain integer

2020-06-20 Thread Chris Angelico
On Sun, Jun 21, 2020 at 2:02 AM Boris Dorestand  wrote:
>
> I just wrote
>
> def f(y, N, k = None):
>   k = k or (N - 1)
>   return k
>
> I was surprised to find out that 0 == False, so f(7, 31, 0) produces 31.
>
> I'd like 0 to be a valid choice for k.
>
> How do you guys let k be an optional argument such that it defaults to
> N - 1?
>

The easiest way is to explicitly check for None.

if k is None: k = N - 1

Zero being false shouldn't be a surprise. If None can count as false,
then so should other "emptiness" values. (Remember, the canonical
falseness value is False, not None.)

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


how to let argument be optional falling back to certain integer

2020-06-20 Thread Boris Dorestand
I just wrote

def f(y, N, k = None):
  k = k or (N - 1)
  return k

I was surprised to find out that 0 == False, so f(7, 31, 0) produces 31.

I'd like 0 to be a valid choice for k.  

How do you guys let k be an optional argument such that it defaults to 
N - 1?  

Thank you.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How to test?

2020-06-20 Thread Mats Wichmann
On 5/1/20 2:34 PM, DL Neil via Python-list wrote:
>>> Given your replies, 'now' might be a good time to take a look at
>>> Pytest, and see how you could use it to help build better code - by
>>> building tested units/functions which are assembled into ever-larger
>>> tested-units... (there is a range of choice/other testing aids if
>>> Pytest doesn't take your fancy)
>>
>> I have to admit I chose unittest. Simply because it is in the standard
>> lbrary. As so many people seem to prefer pytest I should take a look at
>> it.
> 
> Not at all! This is a personal bias - I happen to have been using Pytest.

it doesn't have to be either-or; pytest can deal with unittest tests,
with some limitations. See here for some notes:

https://docs.pytest.org/en/stable/unittest.html

so you can try out what you have under pytest, and if liking it, can
begin to transition to more native pytest - or just keep it as the test
runner, or just stick with unittest.



-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How to test?

2020-06-20 Thread Stephen Rosen
Worth noting: by assertTrue he probably meant assertEqual.
But I'd recommend using assertIn [1] if you're using unittest to check
output written to stdout/stderr.
That way, your tests are slightly more robust to changes in the exact
output.


pytest may also be helpful for this (or any!) type of testing.
Disclaimer/warning: pytest can be confusing even for experienced python
programmers because it does some fancy things.
But if you put in the time to learn it, it's very popular because of the
way it structures testsuites and code reuse (i.e. fixtures).

It can do a lot to help you, and provides output capturing out of the box
[2] as well as some handy tools for building temporary testing directories
[3].


[1]
https://docs.python.org/3.6/library/unittest.html#unittest.TestCase.assertIn
[2] https://docs.pytest.org/en/stable/capture.html
[3] https://docs.pytest.org/en/stable/tmpdir.html

On Fri, Jun 19, 2020 at 2:18 PM Terry Reedy  wrote:

> On 6/17/2020 12:34 PM, Tony Flury via Python-list wrote:
>
> > In a recent application that I wrote (where output to the console was
> > important), I tested it using the 'unittest' framework, and by patching
> > sys.stderr to be a StringIO - that way my test case could inspect what
> > was being output.
>
> Tony's code with hard returns added so that code lines remain separated
> instead of wrapping.
>
> with patch('sys.stderr', StringIO()) as stderr:
>application.do_stuff()  self.assertTrue(stderr.getvalue(),
>'Woops - that didn\'t work')
> This doc, worth reading more than once, is
> https://docs.python.org/3/library/unittest.mock.html#the-patchers
>
> --
> Terry Jan Reedy
>
> --
> https://mail.python.org/mailman/listinfo/python-list
>
-- 
https://mail.python.org/mailman/listinfo/python-list