--
You received this message because you are subscribed to the Google Groups "fltk.general" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fltkgeneral...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/fltkgeneral/EC0ADDA5-E44B-473D-ADB2-9061BC347F34%40gmail.com.
FLTK already has a lock exactly like this. Calling code (for instance your python wrappers for any fltk functions) should lock before calling anything.There is a hack so if nobody calls the lock() it does not interfere with the operation of a single-threaded program, which is probably why you don't know it exists.Calling Fl::run() or other functions that process events is pretty much the "start the gui" call. Whatever thread does this will become the main thread as far as fltk is concerned.As you know, there are unfortunately a bunch of fltk calls that assume they are running in the main thread, especially on Windows. Grabbing the lock does not help. It would be nice to fix this but it is unusual that you have to work around it, in particular because any callbacks will execute in the main thread.If you want a callback to run python code you must grab the Python GIL.
On Sat, Jan 15, 2022 at 3:32 AM Ian MacArthur wrote:
Hi Rob,
On 15 Jan 2022, at 06:53, Rob McDonald wrote:
>
> To do this, I think we need to...
>
> Add a StartGUI() routine to the API that will start a new thread, open the default GUI windows, and start the event loop (basically do what main() does for the interactive program). The original thread will return control to Python.
>
> Add a lock that prevents truly simultaneous access. Whenever an event comes in, FLTK must acquire the lock before calling into my code to handle the event. Once the event is fully handled (and control returns to the event loop), the lock is released.
>
> At the same time, every API call must acquire the lock before doing anything. The lock will be released when the API call is finished.
>
> Acquiring the lock will be blocking -- whether from the GUI or the API, if the program is busy, you'll see some lag or hesitation. However, much of the time, you will be able to interact normally with the program.
>
> Is this the right idea? Do I have a fundamental misunderstanding here? Can anyone point at an example application that takes this approach?
>
> Thanks in advance for any help,
I think the idea is OK, but I’m uncomfortable about the proposed implementation.
The crux, for me, is that this ends up with the fltk GUI context running in a “non-main” thread - and that, basically, is not going to be robust, I fear.
A lot (some | many | most) systems are such that the GUI context “belongs" to the main thread of a process, and GPU drivers are built for speed, not safety, and the result is that modifying the GUI context from a non-main thread can be “fragile”, though the fragility can vary from GPU to GPU. (The usual manifestation of this is bugs or crashes “elsewhere” in the program due to pointer corruptions etc. which can be insanely difficult to debug.)
Further, at least on Windows hosts, event delivery (at the OS level, not the fltk level) can be “tricky" to non-main threads.
If the Python thread *also* has a GUI, then things can get really nasty pretty quickly.
So: It might work (or at least appear to work, on some hosts, anyway) but I suspect it would just lead to pain.
Where I’ve done this in the past, I usually just spawn a whole new process and have the two processes communicate, e.g. via pipes or etc.
If this has to run on Win32 hosts as well, then I use (localhost) network sockets between the processes rather than pipes - this simply because the fltk Fl::add_fd() can pend on Windows network sockets, but not on Windows pipes (on Posix hosts add_fd() will happily listen to any suitable fd, it is only Win32 that is “weak” in this regard.)
FWIW, localhost network sockets on Win32 are cheap and high bandwidth, so it’s a pretty easy way to pass the IPC between the processes anyway - and has the advantage that, by simply setting the address to something other than 127.0.0.1 you can then split the app over two separate systems “for free” as it were.
FlpyMETHOD_VARARGS_BEGIN(Widget, align)
FlpyARG_I_TO_v_TYPE(Widget, align, Fl_Align)
FlpyARG_v_TO_i(Widget, align)
FlpyMETHOD_VARARGS_END(Widget, align, "takes no arguments or a single alignment value"),
implements Fl_Align Fl_Widget::align() and void Fl_Widget::align(Fl_Align), but as I said, so far I am only playing around.Sorry, this time from the laptop without the typos from the phone:https://github.com/MatthiasWM/fltk/tree/python2CMake …. -DFLTK_PYTHON_BINDINGS=onCMake —build —target=python_testI am somewhat new to Python. The Swig stuff is a great concept, but pyFLTK has a few flaws (GC will delete widgets if they are not assigned to a global variable, for example). So I put a little bit of time in to try to write better Python bindings using the Python C API directly..
The link above implements the Fl_Widget class and shows that derived widgets can be easily added (Fl_Button in this example, Fl_Group to follow). My code has almost no overlap with the git GIT repo. Most stuff is in `src/bindings` plus a few lines for CMake, and a `python_test` app.
On Sunday, April 2, 2023 at 4:21:32 PM UTC-7 Matthias Melcher wrote:Hi Matthias, I help with the pyFltk project. I'm very interested in your effort to create a Python binding for FLTK. I cloned your repo and checked out the python2 branch but I must be missing something as the build command did not work (using Debian 12).
Also, I think the GC issue is a feature of Python itself (or maybe I am not understanding your comment).
The link above implements the Fl_Widget class and shows that derived widgets can be easily added (Fl_Button in this example, Fl_Group to follow). My code has almost no overlap with the git GIT repo. Most stuff is in `src/bindings` plus a few lines for CMake, and a `python_test` app.
Manually writing ALL widgets seems like a lot of work compared to using a wrapper tool like Swig.
BTW one of the nice features of the pyFltk project is that it's able to duplicate the function overload abilities of C++ FLTK (like get/set methods where leaving out function args is a get and providing them is a set) using Python.
rob...@gmail.com schrieb am Samstag, 8. April 2023 um 08:52:38 UTC+2:
On Sunday, April 2, 2023 at 4:21:32 PM UTC-7 Matthias Melcher wrote:
Hi Matthias, I help with the pyFltk project. I'm very interested in your effort to create a Python binding for FLTK. I cloned your repo and checked out the python2 branch but I must be missing something as the build command did not work (using Debian 12).
Only the CMake build works. I did a few changes, so it may not compile at all times. It's important to set the compiler to C++11. I use `cmake -B build . -DFLTK_PYTHON_BINDINGS=on -DCMAKE_CXX_STANDARD=11` and `cmake --build build`Also, I think the GC issue is a feature of Python itself (or maybe I am not understanding your comment).
I saw that Python sample code always declares global variables for Widgets, even though the variables are never used. It seems that not assigning variable will cause the GC to delete a widget, even though it is still used by the parent widget. This is a bug in the pyFLTK bindings IMHO, but it is also very possible that I am diagnosing this wrong.
No you are diagnosing it right.
With pybind11 you can choose what classes are reference counted and which ones are not. And you can call release() to clear the object, without effecting the reference count.
https://pybind11.readthedocs.io/en/stable/advanced/cast/custom.html#manual-reference-counting
BTW one of the nice features of the pyFltk project is that it's able to duplicate the function overload abilities of C++ FLTK (like get/set methods where leaving out function args is a get and providing them is a set) using Python.
Yes, I saw that and that's great.
function( X=10 )
You can also use default arguments for python.
I saw that Python sample code always declares global variables for Widgets, even though the variables are never used. It seems that not assigning variable will cause the GC to delete a widget, even though it is still used by the parent widget. This is a bug in the pyFLTK bindings IMHO, but it is also very possible that I am diagnosing this wrong.
Matthias can you please provide a link or dir/filename of the python sample code you are referring to regarding the global variable issue.
Thanks for the explanations and patience. I'll have some more fun with Python soon.
--
You received this message because you are subscribed to the Google Groups "fltk.general" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fltkgeneral...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/fltkgeneral/d64e609e-d523-42d3-afdf-8d5a6dbf13den%40googlegroups.com.
I think you could make things mostly work as expected by having destruction of the Python object only destroy the FLTK widget if the widget does not have a parent.Any widget with a parent is assumed to be destroyed when the parent is destroyed. That would allow you to create/destroy widgets in Python normally, but if you add them to a larger FLTK object and forget about them, they don't get destroyed.
--
You received this message because you are subscribed to the Google Groups "fltk.general" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fltkgeneral...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/fltkgeneral/CACbaDy74MqZK2jgNQWAuv-o4140p_f31M%3DR9v2nThuTjfh-6Bw%40mail.gmail.com.