Discussion:
A new approach for Qt main()
(too old to reply)
Morten Sorvig
2016-12-09 09:35:04 UTC
Permalink
Hi,

We should consider changing the way Qt initialization and startup works.
This is something I’ve personally been wanting to do for some time, and
a recent offline discussion pushed it on my stack again.

Currently, Qt and application startup looks something like this:

int main(int argc, char **argv)
{
QApplication app(argc, argv);

// Create root user objects/windows here

return app.exec();
}

This is fine for the application but cause problems for the Qt platform
implementation, which include:

* The main entry point may be named something else than main()

* The main entry point may be a callback which must be returned from

* The platform/Qt/application initialization order is incorrect

These have all been worked around in Qt platform code, for example by running
Qt on a separate thread, using setjmp/longjmp to simulate a stack, or by
temporarily setting up the native event loop before app.exec() is called.

We can continue with the workarounds, but they lead to complications in Qt
platform code and are also an extra hurdle for implementing support for new
platforms, so from the Qt platform development point of view it is desirable
with a cleanup.

This would be an “all applications should/must port” event, not to be taken
lightly. I think the porting would be trivial in many (if not most) cases,
but some apps have special requirements for QApplication object management
or main thread ownership. This includes our own QTestLib.

As a starting point for a concrete API discussion I’ll briefly describe the
solution I implemented for the NaCl port. The user API here is a macro which
takes application init and exit callback functions:

Q_GUI_MAIN(appInit, appExit);

The use of a macro allows Qt to inject a main() call with native platform
initialization code into the application, if needed. The init and exit
functions are callbacks (which must return) and the root user objects
must be created on the heap. The QApplication object is managed by Qt
and has been created by the time appInit is called. The type of QApplication
is decided by the macro, where there are CORE and WIDGETS variants as well.

- Morten
Jake Petroules
2016-12-09 09:42:37 UTC
Permalink
Without getting too much into the technical details, I'm all for it in principle. It would certainly help on iOS especially as there's a lot of complexity for the main() situation there, which is made even worse by trying to support dynamic libraries.

Can you give an example of what the definition of QT_GUI_MAIN would look like and what are the signatures of appInit and appExit?

> On Dec 9, 2016, at 1:35 AM, Morten Sorvig <***@qt.io> wrote:
>
> Hi,
>
> We should consider changing the way Qt initialization and startup works.
> This is something I’ve personally been wanting to do for some time, and
> a recent offline discussion pushed it on my stack again.
>
> Currently, Qt and application startup looks something like this:
>
> int main(int argc, char **argv)
> {
> QApplication app(argc, argv);
>
> // Create root user objects/windows here
>
> return app.exec();
> }
>
> This is fine for the application but cause problems for the Qt platform
> implementation, which include:
>
> * The main entry point may be named something else than main()
>
> * The main entry point may be a callback which must be returned from
>
> * The platform/Qt/application initialization order is incorrect
>
> These have all been worked around in Qt platform code, for example by running
> Qt on a separate thread, using setjmp/longjmp to simulate a stack, or by
> temporarily setting up the native event loop before app.exec() is called.
>
> We can continue with the workarounds, but they lead to complications in Qt
> platform code and are also an extra hurdle for implementing support for new
> platforms, so from the Qt platform development point of view it is desirable
> with a cleanup.
>
> This would be an “all applications should/must port” event, not to be taken
> lightly. I think the porting would be trivial in many (if not most) cases,
> but some apps have special requirements for QApplication object management
> or main thread ownership. This includes our own QTestLib.
>
> As a starting point for a concrete API discussion I’ll briefly describe the
> solution I implemented for the NaCl port. The user API here is a macro which
> takes application init and exit callback functions:
>
> Q_GUI_MAIN(appInit, appExit);
>
> The use of a macro allows Qt to inject a main() call with native platform
> initialization code into the application, if needed. The init and exit
> functions are callbacks (which must return) and the root user objects
> must be created on the heap. The QApplication object is managed by Qt
> and has been created by the time appInit is called. The type of QApplication
> is decided by the macro, where there are CORE and WIDGETS variants as well.
>
> - Morten
>
>
>
>
>
>
> _______________________________________________
> Development mailing list
> ***@qt-project.org
> http://lists.qt-project.org/mailman/listinfo/development

--
Jake Petroules - ***@qt.io
The Qt Company - Silicon Valley
Qbs build tool evangelist - qbs.io
Friedemann Kleint
2016-12-09 10:00:00 UTC
Permalink
Hi,

> Q_GUI_MAIN(appInit, appExit);

Magic macros for main should be avoided, IMO.

A typical application main() can look like

main()
{
QApplication a();

Initialization code for other libraries

parseArguments(), return if failed

show some FileDialog prompting for argument if sth was missing

try {
app.exec()
} catch (exception) {
}
De-Initialize something
}

There is no way to shoehorn this into some macro; this can already be
observed when trying to adding some initialization to a test.

Regards,
Friedemann

--

Friedemann Kleint
The Qt Company GmbH
Simon Hausmann
2016-12-09 10:17:27 UTC
Permalink
Yes, and we will forever (?) support that kind of main function and application entry point. I don't think that we can break that.


I'm all interested in supporting a second supported way of describing an entry point that more closely matches today's semantics

of graphics applications on the underlying operating/windowing systems.


Oddly, I do like the way that we're doing this on Windows and have been doing it forever, by shoehorning main() into WinMain()

through a static library. I'm not suggesting to replace QtMain, but I wonder if we could offer a cross-platform QtMain (with a different

name that doesn't clash with the existing one) that requires the programmer to supply a _two_ (or more?) functions instead of one function. No

macros involved then.



Simon

________________________________
From: Development <development-bounces+simon.hausmann=***@qt-project.org> on behalf of Friedemann Kleint <***@qt.io>
Sent: Friday, December 9, 2016 11:00:00 AM
To: ***@qt-project.org
Subject: Re: [Development] A new approach for Qt main()

Hi,

> Q_GUI_MAIN(appInit, appExit);

Magic macros for main should be avoided, IMO.

A typical application main() can look like

main()
{
QApplication a();

Initialization code for other libraries

parseArguments(), return if failed

show some FileDialog prompting for argument if sth was missing

try {
app.exec()
} catch (exception) {
}
De-Initialize something
}

There is no way to shoehorn this into some macro; this can already be
observed when trying to adding some initialization to a test.

Regards,
Friedemann

--

Friedemann Kleint
The Qt Company GmbH
Laszlo Agocs
2016-12-09 10:41:52 UTC
Permalink
Special macros for straightforward applications on exotic systems? Sure. Forcing an unnecessary change on existing and future applications on platforms that are doing just fine (i.e. the majority)? No.

Building on Friedemann's example the list of potentially problematic cases could go on forever. For example, what if you need to set certain application attributes, default surface formats, etc. before the Q(Gui)Application construction. Or the special cases where app object creation should be carefully placed. In the end those macros would need to get a lot more complicated than they look at first. Based on all the negative experience with testlib's similar and the qtdeclarative examples' main-wrapping macros, I'd rather prefer we think twice before introducing any such macros.

Also, if migration for the typical applications is seen that easy, it should be no problem for developers targeting exotic systems to provide a new-style entry point in their apps.

Best regards,
Laszlo

From: Development [mailto:development-bounces+laszlo.agocs=***@qt-project.org] On Behalf Of Simon Hausmann
Sent: Friday, December 9, 2016 11:17 AM
To: Friedemann Kleint <***@qt.io>; ***@qt-project.org
Subject: Re: [Development] A new approach for Qt main()




Yes, and we will forever (?) support that kind of main function and application entry point. I don't think that we can break that.



I'm all interested in supporting a second supported way of describing an entry point that more closely matches today's semantics

of graphics applications on the underlying operating/windowing systems.



Oddly, I do like the way that we're doing this on Windows and have been doing it forever, by shoehorning main() into WinMain()

through a static library. I'm not suggesting to replace QtMain, but I wonder if we could offer a cross-platform QtMain (with a different

name that doesn't clash with the existing one) that requires the programmer to supply a _two_ (or more?) functions instead of one function. No

macros involved then.





Simon

________________________________
From: Development <development-bounces+simon.hausmann=***@qt-project.org<mailto:development-bounces+simon.hausmann=***@qt-project.org>> on behalf of Friedemann Kleint <***@qt.io<mailto:***@qt.io>>
Sent: Friday, December 9, 2016 11:00:00 AM
To: ***@qt-project.org<mailto:***@qt-project.org>
Subject: Re: [Development] A new approach for Qt main()

Hi,

> Q_GUI_MAIN(appInit, appExit);

Magic macros for main should be avoided, IMO.

A typical application main() can look like

main()
{
QApplication a();

Initialization code for other libraries

parseArguments(), return if failed

show some FileDialog prompting for argument if sth was missing

try {
app.exec()
} catch (exception) {
}
De-Initialize something
}

There is no way to shoehorn this into some macro; this can already be
observed when trying to adding some initialization to a test.

Regards,
Friedemann

--

Friedemann Kleint
The Qt Company GmbH
Morten Sorvig
2016-12-09 14:34:47 UTC
Permalink
> On 9 Dec 2016, at 11:41, Laszlo Agocs <***@qt.io> wrote:
>
>
> Special macros for straightforward applications on exotic systems? Sure. Forcing an unnecessary change on existing and future applications on platforms that are doing just fine (i.e. the majority)? No.
>
<snip>

>
> Also, if migration for the typical applications is seen that easy, it should be no problem for developers targeting exotic systems to provide a new-style entry point in their apps.

I think we should have one primary way to handle app init though, which would be mentioned first in the documentation and which most of the examples use. So I would prefer to keep the current API if we can’t find a new primary API.

Morten
Lars Knoll
2016-12-09 10:44:24 UTC
Permalink
Well, the problem is that the main() entry point is causing huge amounts of issues on at least Android and iOS. We’d help those platforms a lot if we didn’t support this kind of entry point (on those platforms) anymore. But I agree that we can’t break this in Qt 5, but we can prepare for Qt6.

I’d propose to define a new entry point that works better on these platforms and offering that as the recommended way for new apps. The best solution is probably a static library that provides callbacks that can be used to initialize things.

When we then come to Qt6, we could deprecate using main() as the entry point, and remove support for it at least on the platforms where this is problematic.

Cheers,
Lars

From: Development <development-bounces+lars.knoll=***@qt-project.org> on behalf of Simon Hausmann <***@qt.io>
Date: Friday, 9 December 2016 at 11:17
To: Friedemann Kleint <***@qt.io>, Qt development mailing list <***@qt-project.org>
Subject: Re: [Development] A new approach for Qt main()




Yes, and we will forever (?) support that kind of main function and application entry point. I don't think that we can break that.



I'm all interested in supporting a second supported way of describing an entry point that more closely matches today's semantics

of graphics applications on the underlying operating/windowing systems.



Oddly, I do like the way that we're doing this on Windows and have been doing it forever, by shoehorning main() into WinMain()

through a static library. I'm not suggesting to replace QtMain, but I wonder if we could offer a cross-platform QtMain (with a different

name that doesn't clash with the existing one) that requires the programmer to supply a _two_ (or more?) functions instead of one function. No

macros involved then.





Simon

________________________________
From: Development <development-bounces+simon.hausmann=***@qt-project.org> on behalf of Friedemann Kleint <***@qt.io>
Sent: Friday, December 9, 2016 11:00:00 AM
To: ***@qt-project.org
Subject: Re: [Development] A new approach for Qt main()

Hi,

> Q_GUI_MAIN(appInit, appExit);

Magic macros for main should be avoided, IMO.

A typical application main() can look like

main()
{
QApplication a();

Initialization code for other libraries

parseArguments(), return if failed

show some FileDialog prompting for argument if sth was missing

try {
app.exec()
} catch (exception) {
}
De-Initialize something
}

There is no way to shoehorn this into some macro; this can already be
observed when trying to adding some initialization to a test.

Regards,
Friedemann

--

Friedemann Kleint
The Qt Company GmbH

_______________________________________________
Development mailing list
***@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development
Filippo Cucchetto
2016-12-09 11:07:53 UTC
Permalink
Does this relates to moving Qt main loop to a different thread other than
the main thread? Cause currently creating the QtApp from a different thread
causes problems. In particular the plugins static objects are destroyed at
app exit and thus on the main thread (and this causes problems because
QObjects should be freed in the same thread where they've created). An
example is the QQmlComponentsCache.



Il 09 dic 2016 11:44, "Lars Knoll" <***@qt.io> ha scritto:

> Well, the problem is that the main() entry point is causing huge amounts
> of issues on at least Android and iOS. We’d help those platforms a lot if
> we didn’t support this kind of entry point (on those platforms) anymore.
> But I agree that we can’t break this in Qt 5, but we can prepare for Qt6.
>
>
>
> I’d propose to define a new entry point that works better on these
> platforms and offering that as the recommended way for new apps. The best
> solution is probably a static library that provides callbacks that can be
> used to initialize things.
>
>
>
> When we then come to Qt6, we could deprecate using main() as the entry
> point, and remove support for it at least on the platforms where this is
> problematic.
>
>
>
> Cheers,
>
> Lars
>
>
>
> *From: *Development <development-bounces+lars.knoll=***@qt-project.org>
> on behalf of Simon Hausmann <***@qt.io>
> *Date: *Friday, 9 December 2016 at 11:17
> *To: *Friedemann Kleint <***@qt.io>, Qt development mailing
> list <***@qt-project.org>
> *Subject: *Re: [Development] A new approach for Qt main()
>
>
>
>
>
> Yes, and we will forever (?) support that kind of main function and
> application entry point. I don't think that we can break that.
>
>
>
> I'm all interested in supporting a second supported way of describing an
> entry point that more closely matches today's semantics
>
> of graphics applications on the underlying operating/windowing systems.
>
>
>
> Oddly, I do like the way that we're doing this on Windows and have been
> doing it forever, by shoehorning main() into WinMain()
>
> through a static library. I'm not suggesting to replace QtMain, but I
> wonder if we could offer a cross-platform QtMain (with a different
>
> name that doesn't clash with the existing one) that requires the
> programmer to supply a _two_ (or more?) functions instead of one function.
> No
>
> macros involved then.
>
>
>
>
>
> Simon
> ------------------------------
>
> *From:* Development <development-bounces+simon.hausmann=
> ***@qt-project.org> on behalf of Friedemann Kleint <
> ***@qt.io>
> *Sent:* Friday, December 9, 2016 11:00:00 AM
> *To:* ***@qt-project.org
> *Subject:* Re: [Development] A new approach for Qt main()
>
>
>
> Hi,
>
> > Q_GUI_MAIN(appInit, appExit);
>
> Magic macros for main should be avoided, IMO.
>
> A typical application main() can look like
>
> main()
> {
> QApplication a();
>
> Initialization code for other libraries
>
> parseArguments(), return if failed
>
> show some FileDialog prompting for argument if sth was missing
>
> try {
> app.exec()
> } catch (exception) {
> }
> De-Initialize something
> }
>
> There is no way to shoehorn this into some macro; this can already be
> observed when trying to adding some initialization to a test.
>
> Regards,
> Friedemann
>
> --
>
> Friedemann Kleint
> The Qt Company GmbH
>
> _______________________________________________
> Development mailing list
> ***@qt-project.org
> http://lists.qt-project.org/mailman/listinfo/development
>
> _______________________________________________
> Development mailing list
> ***@qt-project.org
> http://lists.qt-project.org/mailman/listinfo/development
>
>
Laszlo Agocs
2016-12-09 11:11:15 UTC
Permalink
There are two separate things in there, though: the entry point and the construction of the Q(Core|Gui)Application object. The problem is with the latter: is it not clear why Morten’s proposal moves that under the framework’s control. Introducing a new entry point, e.g. qtMain(), for all platforms in Qt 6 is fine. Moving the application object construction into the underlying platform-specific entry point Qt provides is not.

Laszlo

From: Development [mailto:development-bounces+laszlo.agocs=***@qt-project.org] On Behalf Of Filippo Cucchetto
Sent: Friday, December 9, 2016 12:08 PM
To: Lars Knoll <***@qt.io>
Cc: Qt Project Development Mailing-List <***@qt-project.org>
Subject: Re: [Development] A new approach for Qt main()

Does this relates to moving Qt main loop to a different thread other than the main thread? Cause currently creating the QtApp from a different thread causes problems. In particular the plugins static objects are destroyed at app exit and thus on the main thread (and this causes problems because QObjects should be freed in the same thread where they've created). An example is the QQmlComponentsCache.



Il 09 dic 2016 11:44, "Lars Knoll" <***@qt.io<mailto:***@qt.io>> ha scritto:
Well, the problem is that the main() entry point is causing huge amounts of issues on at least Android and iOS. We’d help those platforms a lot if we didn’t support this kind of entry point (on those platforms) anymore. But I agree that we can’t break this in Qt 5, but we can prepare for Qt6.

I’d propose to define a new entry point that works better on these platforms and offering that as the recommended way for new apps. The best solution is probably a static library that provides callbacks that can be used to initialize things.

When we then come to Qt6, we could deprecate using main() as the entry point, and remove support for it at least on the platforms where this is problematic.

Cheers,
Lars

From: Development <development-bounces+lars.knoll=***@qt-project.org<mailto:***@qt-project.org>> on behalf of Simon Hausmann <***@qt.io<mailto:***@qt.io>>
Date: Friday, 9 December 2016 at 11:17
To: Friedemann Kleint <***@qt.io<mailto:***@qt.io>>, Qt development mailing list <***@qt-project.org<mailto:***@qt-project.org>>
Subject: Re: [Development] A new approach for Qt main()




Yes, and we will forever (?) support that kind of main function and application entry point. I don't think that we can break that.



I'm all interested in supporting a second supported way of describing an entry point that more closely matches today's semantics

of graphics applications on the underlying operating/windowing systems.



Oddly, I do like the way that we're doing this on Windows and have been doing it forever, by shoehorning main() into WinMain()

through a static library. I'm not suggesting to replace QtMain, but I wonder if we could offer a cross-platform QtMain (with a different

name that doesn't clash with the existing one) that requires the programmer to supply a _two_ (or more?) functions instead of one function. No

macros involved then.





Simon

________________________________
From: Development <development-bounces+simon.hausmann=***@qt-project.org<mailto:***@qt-project.org>> on behalf of Friedemann Kleint <***@qt.io<mailto:***@qt.io>>
Sent: Friday, December 9, 2016 11:00:00 AM
To: ***@qt-project.org<mailto:***@qt-project.org>
Subject: Re: [Development] A new approach for Qt main()

Hi,

> Q_GUI_MAIN(appInit, appExit);

Magic macros for main should be avoided, IMO.

A typical application main() can look like

main()
{
QApplication a();

Initialization code for other libraries

parseArguments(), return if failed

show some FileDialog prompting for argument if sth was missing

try {
app.exec()
} catch (exception) {
}
De-Initialize something
}

There is no way to shoehorn this into some macro; this can already be
observed when trying to adding some initialization to a test.

Regards,
Friedemann

--

Friedemann Kleint
The Qt Company GmbH

_______________________________________________
Development mailing list
***@qt-project.org<mailto:***@qt-project.org>
http://lists.qt-project.org/mailman/listinfo/development

_______________________________________________
Development mailing list
***@qt-project.org<mailto:***@qt-project.org>
http://lists.qt-project.org/mailman/listinfo/development
Friedemann Kleint
2016-12-09 11:31:24 UTC
Permalink
Hi,

from the Windows POV, support for wmain() with wide arguments would be a
nice thing to have (see https://bugreports.qt.io/browse/QTBUG-46118 ):

int wmain( int argc, wchar_t *argv[ ], wchar_t *envp[ ] )

Maybe that can be implemented by some smart modularization.

Regards,
Friedemann

--
Friedemann Kleint
The Qt Company GmbH
Morten Sorvig
2016-12-09 14:34:45 UTC
Permalink
> On 9 Dec 2016, at 12:11, Laszlo Agocs <***@qt.io> wrote:
>
> There are two separate things in there, though: the entry point and the construction of the Q(Core|Gui)Application object. The problem is with the latter: is it not clear why Morten’s proposal moves that under the framework’s control. Introducing a new entry point, e.g. qtMain(), for all platforms in Qt 6 is fine. Moving the application object construction into the underlying platform-specific entry point Qt provides is not.


The reasoning was that QApplication management ended up as boilerplate code, so let’s simplify. This is especially true if the application type has already been selected via a macro.

Keeping support for setting options before creating the application object is a very good argument for letting user code control it though.

Morten
Tor Arne Vestbø
2016-12-09 11:40:17 UTC
Permalink
On 09/12/2016 11:44, Lars Knoll wrote:
> Well, the problem is that the main() entry point is causing huge amounts
> of issues on at least Android and iOS.

I don't know about Android, but on iOS this is patently false. While the
workaround is complex, it has worked very well in the 3 years since its
inception. Please don't use iOS as a straw-man in this discussion.

Tor Arne
Jake Petroules
2016-12-09 11:49:51 UTC
Permalink
> On Dec 9, 2016, at 3:40 AM, Tor Arne Vestbø <***@qt.io> wrote:
>
> On 09/12/2016 11:44, Lars Knoll wrote:
>> Well, the problem is that the main() entry point is causing huge amounts
>> of issues on at least Android and iOS.
>
> I don't know about Android, but on iOS this is patently false. While the workaround is complex, it has worked very well in the 3 years since its inception. Please don't use iOS as a straw-man in this discussion.

The point is that we shouldn't need such a workaround in the first place. That's kind of the point of this discussion. And as I said, the iOS situation is made even worse further by dynamic libraries.

>
> Tor Arne
> _______________________________________________
> Development mailing list
> ***@qt-project.org
> http://lists.qt-project.org/mailman/listinfo/development

--
Jake Petroules - ***@qt.io
The Qt Company - Silicon Valley
Qbs build tool evangelist - qbs.io
Tor Arne Vestbø
2016-12-09 13:02:12 UTC
Permalink
On 09/12/2016 12:49, Jake Petroules wrote:
>> On Dec 9, 2016, at 3:40 AM, Tor Arne Vestbø <***@qt.io>
>> wrote:
>>
>> On 09/12/2016 11:44, Lars Knoll wrote:
>>> Well, the problem is that the main() entry point is causing huge
>>> amounts of issues on at least Android and iOS.
>>
>> I don't know about Android, but on iOS this is patently false.
>> While the workaround is complex, it has worked very well in the 3
>> years since its inception. Please don't use iOS as a straw-man in
>> this discussion.
>
> The point is that we shouldn't need such a workaround in the first
> place. That's kind of the point of this discussion. And as I said,
> the iOS situation is made even worse further by dynamic libraries.

Obviously getting rid of workaround (in all platforms, not just iOS)
would be preferable. But describing the current (x years and counting)
situation as 'causing huge amount of issues' (on iOS) is just plain
wrong, and derails the discussion from pragmatic and constructive
solutions to the problem.

tor arne
Jake Petroules
2016-12-09 13:10:50 UTC
Permalink
> On Dec 9, 2016, at 5:02 AM, Tor Arne Vestbø <***@qt.io> wrote:
>
> On 09/12/2016 12:49, Jake Petroules wrote:
>>> On Dec 9, 2016, at 3:40 AM, Tor Arne Vestbø <***@qt.io>
>>> wrote:
>>>
>>> On 09/12/2016 11:44, Lars Knoll wrote:
>>>> Well, the problem is that the main() entry point is causing huge
>>>> amounts of issues on at least Android and iOS.
>>>
>>> I don't know about Android, but on iOS this is patently false.
>>> While the workaround is complex, it has worked very well in the 3
>>> years since its inception. Please don't use iOS as a straw-man in
>>> this discussion.
>>
>> The point is that we shouldn't need such a workaround in the first
>> place. That's kind of the point of this discussion. And as I said,
>> the iOS situation is made even worse further by dynamic libraries.
>
> Obviously getting rid of workaround (in all platforms, not just iOS) would be preferable. But describing the current (x years and counting) situation as 'causing huge amount of issues' (on iOS) is just plain wrong, and derails the discussion from pragmatic and constructive solutions to the problem.

Again, I think you're missing Lars' point - "causing huge amount of issues" doesn't necessarily mean that we are constantly finding and fixing issues every week - in this context it means "the fact that we have a workaround at all", i.e. a suboptimal solution to an architectural problem that we wish wasn't there. Even ONE issue (the one that was "fixed" years ago) can still qualify as "huge amount of issues" simply because the solution in place is complicated and we don't like it.

I think at this point we're nitpicking linguistics. We both understood what Lars meant and obviously both agree with him.

> tor arne

--
Jake Petroules - ***@qt.io
The Qt Company - Silicon Valley
Qbs build tool evangelist - qbs.io
Tor Arne Vestbø
2016-12-09 13:22:17 UTC
Permalink
On 09/12/2016 14:10, Jake Petroules wrote:
> Again, I think you're missing Lars' point - "causing huge amount of
> issues" doesn't necessarily mean that we are constantly finding and
> fixing issues every week - in this context it means "the fact that we
> have a workaround at all", i.e. a suboptimal solution to an
> architectural problem that we wish wasn't there. Even ONE issue (the
> one that was "fixed" years ago) can still qualify as "huge amount of
> issues" simply because the solution in place is complicated and we
> don't like it.

Yes, linguistics is quite important when trying to make a point over the
internet. For example using the present tense "causing" instead of past
tense. The fact that you personally have some sort of allergic reaction
to the current situation, based on the strong argument of "not liking
it", is not of much concern to me in shaping the future solution in this
area.

tor arne
Eskil Abrahamsen Blomfeldt
2016-12-09 11:58:46 UTC
Permalink
Den 09.12.2016 12:40, skrev Tor Arne Vestbø:
> On 09/12/2016 11:44, Lars Knoll wrote:
>> Well, the problem is that the main() entry point is causing huge amounts
>> of issues on at least Android and iOS.
>
> I don't know about Android, but on iOS this is patently false. While
> the workaround is complex, it has worked very well in the 3 years
> since its inception. Please don't use iOS as a straw-man in this
> discussion.

Speaking for Android, there are and have been thread synchronization
issues due to Qt running a synchronous event loop in the main function.
It is also impossible to make applications with multiple entry points
and complex life cycles, which you would expect in an Android
application consisting of several activities and services that can be
triggered independently and simultaenously. Our work-around for this is
to limit support to applications with one activity or one service per
process in the application.

So while we have been able to find solutions for most our problems, both
on Android and iOS, I guess Lars' point is that we are encountering more
and more cases where we have to invent hacks and work-arounds and
document limitations in order to be functional on modern platforms. It
might be a sign that we should adapt.

--
Eskil Abrahamsen Blomfeldt
Senior Manager, R&D

The Qt Company
Sandakerveien 116
0484 Oslo, Norway
eskil.abrahamsen-***@qt.io
http://qt.io
Tor Arne Vestbø
2016-12-09 13:10:03 UTC
Permalink
On 09/12/2016 12:58, Eskil Abrahamsen Blomfeldt wrote:
> Den 09.12.2016 12:40, skrev Tor Arne Vestbø:
>> On 09/12/2016 11:44, Lars Knoll wrote:
>>> Well, the problem is that the main() entry point is causing huge amounts
>>> of issues on at least Android and iOS.
>>
>> I don't know about Android, but on iOS this is patently false. While
>> the workaround is complex, it has worked very well in the 3 years
>> since its inception. Please don't use iOS as a straw-man in this
>> discussion.
>
> Speaking for Android, there are and have been thread synchronization
> issues due to Qt running a synchronous event loop in the main function.
> It is also impossible to make applications with multiple entry points
> and complex life cycles, which you would expect in an Android
> application consisting of several activities and services that can be
> triggered independently and simultaenously. Our work-around for this is
> to limit support to applications with one activity or one service per
> process in the application.
>
> So while we have been able to find solutions for most our problems, both
> on Android and iOS, I guess Lars' point is that we are encountering more
> and more cases where we have to invent hacks and work-arounds and
> document limitations in order to be functional on modern platforms. It
> might be a sign that we should adapt.

Yes, I'm not disagreeing that a new model for Qt initialization would be
welcome, I was reacting to the swiping generalization Lars was making in
trying to make his point :-)

tor arne
Bogdan Vatra
2016-12-09 13:19:27 UTC
Permalink
On vineri, 9 decembrie 2016 12:58:46 EET Eskil Abrahamsen Blomfeldt wrote:
> Den 09.12.2016 12:40, skrev Tor Arne Vestbø:
> > On 09/12/2016 11:44, Lars Knoll wrote:
> >> Well, the problem is that the main() entry point is causing huge amounts
> >> of issues on at least Android and iOS.
> >
> > I don't know about Android, but on iOS this is patently false. While
> > the workaround is complex, it has worked very well in the 3 years
> > since its inception. Please don't use iOS as a straw-man in this
> > discussion.
>
> Speaking for Android, there are and have been thread synchronization
> issues due to Qt running a synchronous event loop in the main function.
> It is also impossible to make applications with multiple entry points
> and complex life cycles, which you would expect in an Android
> application consisting of several activities and services that can be
> triggered independently and simultaenously. Our work-around for this is
> to limit support to applications with one activity or one service per
> process in the application.
>
> So while we have been able to find solutions for most our problems, both
> on Android and iOS, I guess Lars' point is that we are encountering more
> and more cases where we have to invent hacks and work-arounds and
> document limitations in order to be functional on modern platforms. It
> might be a sign that we should adapt.

IMHO (at least) for Android the biggest problem is the QPA architecture which
is not designed for multiple Activities/Services. On Android we'll need a QPA
instance for every Activities/Services :). This also means we'll need to
redesign QtAndroidExtras as well.

Even if having multiple Activities in the same process will be a nice thing,
is not a very demanding feature. The most demanding feature will be to support
multiple Services alongside an Activity in the same process.

Cheers,
BogDan.
Andre Poenitz
2016-12-09 13:51:19 UTC
Permalink
Whatever the problem is, I think we should try hard to have a solution
that 1. does not use macros and 2. that does not optically change the
int main(int argc, char *argv[]) { QApplication app(argc, argv)... } stanza.

Macros look and feel ugly and outdated in contemporary C++, are harder
to debug, etc etc. Changing away from a normal main will make look Qt
code alien, not to mention the necessary adaptation in documentation
and each and every "getting started with Qt" tutorial out there. This would
be a high price to pay.

I have to admit that I don't really understand the scope of the problem yet.
If this is about having customization points in the QApplication object's life
cycle, or supporting multiple entry points or similar one could have e.g.
a number of QApplication::setFooCustomization(std::function<...>)
static functions that can be used to register callbacks by the platform
specific Qt and/or user code. Also, the actual "application object"
lifecycle does not have to be match the user's QApplication object
in main(). The real thing can be created whenever it make sense, and
what the user sees will only forward calls, or hold back calls, or possible
finalize initialization or whatever using the registered callbacks.

For me it would be helpful to have a list of problems that need to be
solved before discussing one specific potential solution.

Andre'


________________________________________
From: Development <development-bounces+andre.poenitz=***@qt-project.org> on behalf of Lars Knoll <***@qt.io>
Sent: Friday, December 9, 2016 11:44 AM
To: Simon Hausmann; Friedemann Kleint; ***@qt-project.org
Subject: Re: [Development] A new approach for Qt main()

Well, the problem is that the main() entry point is causing huge amounts of issues on at least Android and iOS. We’d help those platforms a lot if we didn’t support this kind of entry point (on those platforms) anymore. But I agree that we can’t break this in Qt 5, but we can prepare for Qt6.

I’d propose to define a new entry point that works better on these platforms and offering that as the recommended way for new apps. The best solution is probably a static library that provides callbacks that can be used to initialize things.

When we then come to Qt6, we could deprecate using main() as the entry point, and remove support for it at least on the platforms where this is problematic.

Cheers,
Lars

From: Development <development-bounces+lars.knoll=***@qt-project.org> on behalf of Simon Hausmann <***@qt.io>
Date: Friday, 9 December 2016 at 11:17
To: Friedemann Kleint <***@qt.io>, Qt development mailing list <***@qt-project.org>
Subject: Re: [Development] A new approach for Qt main()




Yes, and we will forever (?) support that kind of main function and application entry point. I don't think that we can break that.



I'm all interested in supporting a second supported way of describing an entry point that more closely matches today's semantics

of graphics applications on the underlying operating/windowing systems.



Oddly, I do like the way that we're doing this on Windows and have been doing it forever, by shoehorning main() into WinMain()

through a static library. I'm not suggesting to replace QtMain, but I wonder if we could offer a cross-platform QtMain (with a different

name that doesn't clash with the existing one) that requires the programmer to supply a _two_ (or more?) functions instead of one function. No

macros involved then.





Simon

________________________________
From: Development <development-bounces+simon.hausmann=***@qt-project.org> on behalf of Friedemann Kleint <***@qt.io>
Sent: Friday, December 9, 2016 11:00:00 AM
To: ***@qt-project.org
Subject: Re: [Development] A new approach for Qt main()

Hi,

> Q_GUI_MAIN(appInit, appExit);

Magic macros for main should be avoided, IMO.

A typical application main() can look like

main()
{
QApplication a();

Initialization code for other libraries

parseArguments(), return if failed

show some FileDialog prompting for argument if sth was missing

try {
app.exec()
} catch (exception) {
}
De-Initialize something
}

There is no way to shoehorn this into some macro; this can already be
observed when trying to adding some initialization to a test.

Regards,
Friedemann

--

Friedemann Kleint
The Qt Company GmbH
Morten Sorvig
2016-12-09 15:29:51 UTC
Permalink
> On 9 Dec 2016, at 14:51, Andre Poenitz <***@qt.io> wrote:
>
>
> Whatever the problem is, I think we should try hard to have a solution
> that 1. does not use macros and 2. that does not optically change the
> int main(int argc, char *argv[]) { QApplication app(argc, argv)... } stanza.

This sounds like the current approach, where we solve the startup issue by
adding complexity to the Qt platform implementation that allows us to keep
main().

The suggested approach would solve the issue by changing the API, and the
motivation is a simplification of the Qt platform implementation. So the
benefit is perhaps not immediately clear to those not directly involved
with Qt platform development, except for the potential for faster developed,
more stable Qt.

>
> Macros look and feel ugly and outdated in contemporary C++, are harder
> to debug, etc etc. Changing away from a normal main will make look Qt
> code alien, not to mention the necessary adaptation in documentation
> and each and every "getting started with Qt" tutorial out there. This would
> be a high price to pay.

Indeed if keeping the normal main (and docs etc) is very important then
that could tip the scales over to not making API changes.

Morten
Thiago Macieira
2016-12-09 17:05:46 UTC
Permalink
Em sexta-feira, 9 de dezembro de 2016, às 10:44:24 PST, Lars Knoll escreveu:
> Well, the problem is that the main() entry point is causing huge amounts of
> issues on at least Android and iOS. We’d help those platforms a lot if we
> didn’t support this kind of entry point (on those platforms) anymore. But I
> agree that we can’t break this in Qt 5, but we can prepare for Qt6.
>
> I’d propose to define a new entry point that works better on these platforms
> and offering that as the recommended way for new apps. The best solution is
> probably a static library that provides callbacks that can be used to
> initialize things.

Can we get a description of what those problems are, for those of us who have
never developed anything for those OSes, so we're not discussing things in the
abstract?

--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
Morten Sorvig
2016-12-12 21:12:31 UTC
Permalink
> On 9 Dec 2016, at 18:05, Thiago Macieira <***@intel.com> wrote:
>
> Em sexta-feira, 9 de dezembro de 2016, às 10:44:24 PST, Lars Knoll escreveu:
>> Well, the problem is that the main() entry point is causing huge amounts of
>> issues on at least Android and iOS. We’d help those platforms a lot if we
>> didn’t support this kind of entry point (on those platforms) anymore. But I
>> agree that we can’t break this in Qt 5, but we can prepare for Qt6.
>>
>> I’d propose to define a new entry point that works better on these platforms
>> and offering that as the recommended way for new apps. The best solution is
>> probably a static library that provides callbacks that can be used to
>> initialize things.
>
> Can we get a description of what those problems are, for those of us who have
> never developed anything for those OSes, so we're not discussing things in the
> abstract?


For some background, here’s what typical application startup looks like on macOS, NaCl, and Emscripten:

macOS: Define the application delegate, create instance of it in main()


// Define application delegate with app lifecycle callbacks
@interface AppDelegate ()
@end

@implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// Init application here
}

- (void)applicationWillTerminate:(NSNotification *)aNotification {
// Tear down here
}
@end

// In main, install application delegate and start the app
int main(int argc, const char *argv[])
{
NSApplication *app = [NSApplication sharedApplication];
app.delegate = [[AppDelegate alloc] initWithArgc:argc argv:argv];
return NSApplicationMain(argc, argv);
}


Native Client: Define pp::CreateModule() and return the application module (which is a
subclass of pp::Module)

namespace pp {
Module* CreateModule() {
return new ApplicationModule();
}
}


Emscripten: implement main()

int main(int argc, const char *argv[) {
// Init application here
return 0;
}

main() should/must return to keep the web page responsive. There is API for
simulating a main that does not return and preserve the stack, see emscripten_set_main_loop()
in the emscripten documentation.


Morten
Thiago Macieira
2016-12-12 21:32:01 UTC
Permalink
Em segunda-feira, 12 de dezembro de 2016, às 21:12:31 PST, Morten Sorvig
escreveu:
> > Can we get a description of what those problems are, for those of us who
> > have never developed anything for those OSes, so we're not discussing
> > things in the abstract?
>
> For some background, here’s what typical application startup looks like on
> macOS, NaCl, and Emscripten:

> macOS: Define the application delegate, create instance of it in main()
>
>
> // Define application delegate with app lifecycle callbacks
> @interface AppDelegate ()
> @end
>
> @implementation AppDelegate
> - (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
> // Init application here
> }
>
> - (void)applicationWillTerminate:(NSNotification *)aNotification {
> // Tear down here
> }
> @end
>
> // In main, install application delegate and start the app
> int main(int argc, const char *argv[])
> {
> NSApplication *app = [NSApplication sharedApplication];
> app.delegate = [[AppDelegate alloc] initWithArgc:argc argv:argv];
> return NSApplicationMain(argc, argv);
> }

Thanks, but the above makes no sense to me. There are a couple of identifiers
in your code that I've never seen before and aren't defined in the application
(NSApplication, NSApplicationMain), plus there's no Qt code anywhere. I don't
know what the code is doing.

I was hoping you'd give some material on how one currently has to integrate Qt
with their platform.

> Native Client: Define pp::CreateModule() and return the application module
> (which is a subclass of pp::Module)
>
> namespace pp {
> Module* CreateModule() {
> return new ApplicationModule();
> }
> }

Ok, this is a factory. That's a very important difference. There's also no
command-line.

Still, I need the example of how one has to integrate with Qt. I have no idea
what the application module is supposed to do, what it can do, when it can do
that, etc.

> Emscripten: implement main()
>
> int main(int argc, const char *argv[) {
> // Init application here
> return 0;
> }
>
> main() should/must return to keep the web page responsive. There is API for
> simulating a main that does not return and preserve the stack, see
> emscripten_set_main_loop() in the emscripten documentation.

And obviously there's something else going on, otherwise the code above does
nothing. In fact, I'm surprised it needs a main function at all...

--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
Edward Welbourne
2016-12-13 13:51:24 UTC
Permalink
Morten Sorvig supplied:

> For some background, here’s what typical application startup looks
> like on macOS, NaCl, and Emscripten:

I've updated [0] to illustrate these.
[0] https://wiki.qt.io/Application_Start-up_Patterns

> macOS: Define the application delegate, create instance of it in main()
>
> // Define application delegate with app lifecycle callbacks
> @interface AppDelegate ()
> @end
>
> @implementation AppDelegate
> - (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
> // Init application here
> }
>
> - (void)applicationWillTerminate:(NSNotification *)aNotification {
> // Tear down here
> }
> @end

Please say more about what has to happen in these, especially init;
presumably, we need to add some handlers to something like an event
queue, to ensure our application gets told what's happening and when to
respond to it.

> // In main, install application delegate and start the app
> int main(int argc, const char *argv[])
> {
> NSApplication *app = [NSApplication sharedApplication];
> app.delegate = [[AppDelegate alloc] initWithArgc:argc argv:argv];
> return NSApplicationMain(argc, argv);
> }

I take it NSApplicationMain(argc, argv) contains a system standard event
loop that looks to the shared NSApplication for its control.

> Native Client: Define pp::CreateModule() and return the application
> module (which is a subclass of pp::Module)
>
> namespace pp {
> Module* CreateModule() {
> return new ApplicationModule();
> }
> }

I need some clue what methods pp::Module allows us to override and how
we can, by doing so, control what the resulting app does.

> Emscripten: implement main()
>
> int main(int argc, const char *argv[) {
> // Init application here
> return 0;
> }
>
> main() should/must return to keep the web page responsive.

I take it, then, that "main()" isn't the whole program, in the classic C
way, just an insertion into an existing running something - into which
we presumably inject some application-specific objects that connect
themselves into the event stream and provide ways to respond.

> There is API for simulating a main that does not return and preserve
> the stack, see emscripten_set_main_loop() in the emscripten
> documentation.

Sounds complicated. Better to fit in naturally with the native system's
preferred modus operandi.

Illustrations (maybe provided by link to existing examples) of how we
presently shoe-horn our existing architecture into the various cases
would be a passable first attempt at answering the open questions ...

Eddy.
Morten Sorvig
2016-12-14 21:52:43 UTC
Permalink
> On 13 Dec 2016, at 14:51, Edward Welbourne <***@qt.io> wrote:
>
> Morten Sorvig supplied:
>
>> For some background, here’s what typical application startup looks
>> like on macOS, NaCl, and Emscripten:
>
> I've updated [0] to illustrate these.
> [0] https://wiki.qt.io/Application_Start-up_Patterns

Thanks!

>
>> macOS: Define the application delegate, create instance of it in main()
>>
>> // Define application delegate with app lifecycle callbacks
>> @interface AppDelegate ()
>> @end
>>
>> @implementation AppDelegate
>> - (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
>> // Init application here
>> }
>>
>> - (void)applicationWillTerminate:(NSNotification *)aNotification {
>> // Tear down here
>> }
>> @end
>
> Please say more about what has to happen in these, especially init;
> presumably, we need to add some handlers to something like an event
> queue, to ensure our application gets told what's happening and when to
> respond to it.


You are correct. On the highest level, the “Init” code would be:

g_application = new QGuiApplicaiton()
// Init application (create app windows etc)

This gives us a nice ordered startup: The native platform has been initialized,
we initialize Qt, and then call application initialization code.

Digging into QGuiApplicaiton construction, it will among other things select
and load a platform plugin, and then ask that platform plugin to create an
event dispatcher, which hooks into the native event queue.

The Qt event dispatcher implementation on macOS supports integrating with
an already running event loop, which is the case here. Calling app.exec()
is not required (and would not work in the callback).


Morten
Matthew Woehlke
2016-12-09 16:10:15 UTC
Permalink
On 2016-12-09 04:35, Morten Sorvig wrote:
> We should consider changing the way Qt initialization and startup works.
> This is something I’ve personally been wanting to do for some time, and
> a recent offline discussion pushed it on my stack again.
>
> Currently, Qt and application startup looks something like this:
>
> int main(int argc, char **argv)
> {
> QApplication app(argc, argv);
>
> // Create root user objects/windows here
>
> return app.exec();
> }
>
> We can continue with the workarounds, but they lead to complications in Qt
> platform code and are also an extra hurdle for implementing support for new
> platforms, so from the Qt platform development point of view it is desirable
> with a cleanup.
>
> This would be an “all applications should/must port” event, not to be taken
> lightly. I think the porting would be trivial in many (if not most) cases,
> but some apps have special requirements for QApplication object management
> or main thread ownership. This includes our own QTestLib.

One concern I have is if users are monkeying with argc/argv prior to
constructing a QApplication instance. IIRC, KDE used to do this (not
sure if they still do), and qtCliArgs¹ does this also. This allows, for
instance, enforcing a consistent argument naming policy that differs
from Qt's own policy, while still being able to pass Qt CLI arguments.

Also, how does this work if someone wants to subclass Q*Application?
(Again, I have projects that do that...)

(¹ https://github.com/Kitware/qtextensions/blob/master/core/qtCliArgs.h)

--
Matthew
Thiago Macieira
2016-12-09 17:10:47 UTC
Permalink
Em sexta-feira, 9 de dezembro de 2016, às 11:10:15 PST, Matthew Woehlke
escreveu:
> Also, how does this work if someone wants to subclass Q*Application?
> (Again, I have projects that do that...)

But why do they do that?

--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
Konstantin Tokarev
2016-12-09 17:13:57 UTC
Permalink
09.12.2016, 20:11, "Thiago Macieira" <***@intel.com>:
>  Em sexta-feira, 9 de dezembro de 2016, às 11:10:15 PST, Matthew Woehlke
>  escreveu:
>>   Also, how does this work if someone wants to subclass Q*Application?
>>   (Again, I have projects that do that...)
>
>  But why do they do that?


To override virtual methods, like notify()

>  --
>  Thiago Macieira - thiago.macieira (AT) intel.com
>    Software Architect - Intel Open Source Technology Center
>
>  _______________________________________________
>  Development mailing list
>  ***@qt-project.org
>  http://lists.qt-project.org/mailman/listinfo/development


--
Regards,
Konstantin
Thiago Macieira
2016-12-09 17:29:56 UTC
Permalink
Em sexta-feira, 9 de dezembro de 2016, às 20:13:57 PST, Konstantin Tokarev
escreveu:
> 09.12.2016, 20:11, "Thiago Macieira" <***@intel.com>:
> > Em sexta-feira, 9 de dezembro de 2016, às 11:10:15 PST, Matthew Woehlke
> >
> > escreveu:
> >> Also, how does this work if someone wants to subclass Q*Application?
> >> (Again, I have projects that do that...)
> >
> > But why do they do that?
>
> To override virtual methods, like notify()

Ok, that's no longer a valid reason because we'll deprecate that practice in
Qt 6.

Any other reasons?

--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
Matthew Woehlke
2016-12-09 20:28:13 UTC
Permalink
On 2016-12-09 12:10, Thiago Macieira wrote:
> Em sexta-feira, 9 de dezembro de 2016, às 11:10:15 PST, Matthew Woehlke
> escreveu:
>> Also, how does this work if someone wants to subclass Q*Application?
>> (Again, I have projects that do that...)
>
> But why do they do that?

...because I have a number of executables which share logic, and it
seemed like the obvious thing to do. (It saves having to create an
entirely separate singleton that interacts closely with QApplication.)

I can work around that, though it's obnoxious. I'm more concerned about
not being able to tinker with the CLI arguments before Qt gets them.

--
Matthew
Thiago Macieira
2016-12-09 21:23:01 UTC
Permalink
Em sexta-feira, 9 de dezembro de 2016, às 15:28:13 PST, Matthew Woehlke
escreveu:
> I can work around that, though it's obnoxious. I'm more concerned about
> not being able to tinker with the CLI arguments before Qt gets them.

That's a valid concern, but not one that warrants a QApplication subclass.

--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
Matthew Woehlke
2016-12-09 21:50:29 UTC
Permalink
On 2016-12-09 16:23, Thiago Macieira wrote:
> Em sexta-feira, 9 de dezembro de 2016, às 15:28:13 PST, Matthew Woehlke
> escreveu:
>> I can work around that, though it's obnoxious. I'm more concerned about
>> not being able to tinker with the CLI arguments before Qt gets them.
>
> That's a valid concern, but not one that warrants a QApplication subclass.

Right; that one is an issue if the user is no longer in control of
instantiating the Q*Application instance.

--
Matthew
Thiago Macieira
2016-12-10 00:43:00 UTC
Permalink
Em sexta-feira, 9 de dezembro de 2016, às 16:50:29 PST, Matthew Woehlke
escreveu:
> On 2016-12-09 16:23, Thiago Macieira wrote:
> > Em sexta-feira, 9 de dezembro de 2016, às 15:28:13 PST, Matthew Woehlke
> >
> > escreveu:
> >> I can work around that, though it's obnoxious. I'm more concerned about
> >> not being able to tinker with the CLI arguments before Qt gets them.
> >
> > That's a valid concern, but not one that warrants a QApplication subclass.
>
> Right; that one is an issue if the user is no longer in control of
> instantiating the Q*Application instance.

Ah, that's a good point.

Though quite frankly I don't see that as an issue. Applications can only have
access to argc and argv if they write the main() function, which means they
can continue to use the current functionality.

I'm imaginiing that this new way is needed for platforms where a main()
function makes no sense, in which case there's no command-line to begin with.

--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
Mark De Wit
2016-12-12 09:56:35 UTC
Permalink
I have an application based on qt-solutions qtwinmigrate sample.

Because we're integrating Qt into an existing MFC application, we're not even running QApplication exec. The application uses MFC's entry point for startup and drives the Qt event loop manually as part of the MFC event loop.

Mark

-----Original Message-----
From: Development [mailto:development-bounces+mark.dewit=***@qt-project.org] On Behalf Of Thiago Macieira
Sent: 10 December 2016 00:43
To: ***@qt-project.org
Subject: Re: [Development] A new approach for Qt main()

Em sexta-feira, 9 de dezembro de 2016, às 16:50:29 PST, Matthew Woehlke
escreveu:
> On 2016-12-09 16:23, Thiago Macieira wrote:
> > Em sexta-feira, 9 de dezembro de 2016, às 15:28:13 PST, Matthew Woehlke
> >
> > escreveu:
> >> I can work around that, though it's obnoxious. I'm more concerned about
> >> not being able to tinker with the CLI arguments before Qt gets them.
> >
> > That's a valid concern, but not one that warrants a QApplication subclass.
>
> Right; that one is an issue if the user is no longer in control of
> instantiating the Q*Application instance.

Ah, that's a good point.

Though quite frankly I don't see that as an issue. Applications can only have
access to argc and argv if they write the main() function, which means they
can continue to use the current functionality.

I'm imaginiing that this new way is needed for platforms where a main()
function makes no sense, in which case there's no command-line to begin with.

--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
Benjamin TERRIER
2016-12-12 10:07:56 UTC
Permalink
2016-12-12 10:56 GMT+01:00 Mark De Wit <***@iesve.com>:
> I have an application based on qt-solutions qtwinmigrate sample.
>
> Because we're integrating Qt into an existing MFC application, we're not even running QApplication exec. The application uses MFC's entry point for startup and drives the Qt event loop manually as part of the MFC event loop.
>
> Mark

I also did something like that on Linux with a software written with
another graphical framework.
We made it work by calling QApplication::processEvents() in the other
framework event loop.

Benjamin
Konstantin Tokarev
2016-12-12 14:49:13 UTC
Permalink
12.12.2016, 13:08, "Benjamin TERRIER" <***@gmail.com>:
> 2016-12-12 10:56 GMT+01:00 Mark De Wit <***@iesve.com>:
>>  I have an application based on qt-solutions qtwinmigrate sample.
>>
>>  Because we're integrating Qt into an existing MFC application, we're not even running QApplication exec. The application uses MFC's entry point for startup and drives the Qt event loop manually as part of the MFC event loop.
>>
>>  Mark
>
> I also did something like that on Linux with a software written with
> another graphical framework.
> We made it work by calling QApplication::processEvents() in the other
> framework event loop.

Same is true for QtWebKit in WebKit2 mode - in background processes we
don't run exec() directly, it is invoked inside WTF::RunLoop.

--
Regards,
Konstantin
Edward Welbourne
2016-12-12 16:11:07 UTC
Permalink
Em sexta-feira, 9 de dezembro de 2016, às 10:44:24 PST, Lars Knoll escreveu:
>>>>> Well, the problem is that the main() entry point is causing huge
>>>>> amounts of issues on at least Android and iOS. We’d help those
>>>>> platforms a lot if we didn’t support this kind of entry point (on
>>>>> those platforms) anymore. But I agree that we can’t break this in
>>>>> Qt 5, but we can prepare for Qt6.
>>>>>
>>>>> I’d propose to define a new entry point that works better on these
>>>>> platforms and offering that as the recommended way for new
>>>>> apps. The best solution is probably a static library that provides
>>>>> callbacks that can be used to initialize things.

On 9 December 2016 18:05, Thiago Macieira replied:

>>>> Can we get a description of what those problems are, for those of
>>>> us who have never developed anything for those OSes, so we're not
>>>> discussing things in the abstract?

I haven't seen an actual reply to that, but these fragments at least
point towards a sketch of the reply:

2016-12-12 10:56 GMT+01:00 Mark De Wit <***@iesve.com>:
>>> I have an application based on qt-solutions qtwinmigrate sample.
>>>
>>> Because we're integrating Qt into an existing MFC application,
>>> we're not even running QApplication exec. The application uses
>>> MFC's entry point for startup and drives the Qt event loop
>>> manually as part of the MFC event loop.

12.12.2016, 13:08, "Benjamin TERRIER" <***@gmail.com>:
>> I also did something like that on Linux with a software written with
>> another graphical framework.
>> We made it work by calling QApplication::processEvents() in the other
>> framework event loop.

12 December 2016 15:49 Konstantin Tokarev
> Same is true for QtWebKit in WebKit2 mode - in background processes we
> don't run exec() directly, it is invoked inside WTF::RunLoop.

and I've heard some conversations over meals, so let's sketch what I
think is the main pattern for which the present architecture is a
problem:
* In some systems, the event loop isn't ours to control.

What that means in practice is that all we can do is register call-backs
to respond to events. Details remain a mystery, but presumably we get
some way to register a "getting started" call-back, which can presumably
register a "shutting down" call-back and assorted call-backs for other
events. I'd like to see detailed descriptions of what the actual
details are, for this, on each of the platforms for which traditional C
main() isn't a good model.

To have one architecture that works for such environments and also works
for the traditional main() context, we need Qt's event loop to be
optional. Something we may as well call QApplication might provide a
default event loop implementation (for main() use), but none of the rest
of our code should presume this is the event loop in use. We need all
our "register handler" APIs to be designed to be agnostic about whose
event loop those handlers get registered to. This shall mean even
Qt-internal events (e.g. those implementing signal/slot interactions)
can be packaged as platform-native events (that Qt shall unpack and
enact when they're delivered).

We should, none the less, be able to package that architecture with
Q*Application objects that *do* provide an event loop so that existing
main() users and tutorials don't need to change what main() looks like;
there might be some changes to how they register handlers and there
shall surely be some changes "under the bonnet" to how moc implements
signals and slots (so that their handling is message-loop-agnostic).

... and that's about as much as I think anyone can say about the future
architecture until someone familiar with the main()-incompatible world
can explain to us all what the contexts are in which the old way fails.
Perhaps we need a Wiki page, detailing the different ways platforms
support start-up and shut-down. So let's have a wiki page for that:
* https://wiki.qt.io/Application_Start-up_Patterns

While I'm at it, I've put that into
* https://wiki.qt.io/Category:Developing_Qt::Architecture
and invite anyone who knows about wiki pages that talk about Qt's
architecture to add them to [[Category:Developing_Qt::Architecture]].
They might be more discoverable that way.

Eddy.
Thiago Macieira
2016-12-12 16:31:57 UTC
Permalink
On segunda-feira, 12 de dezembro de 2016 16:11:07 PST Edward Welbourne wrote:
> I haven't seen an actual reply to that, but these fragments at least
> point towards a sketch of the reply:

We already have a solution for those cases and that's
QAbstractEventDispatcher.

--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
Thiago Macieira
2016-12-12 16:28:54 UTC
Permalink
On segunda-feira, 12 de dezembro de 2016 11:07:56 PST Benjamin TERRIER wrote:
> 2016-12-12 10:56 GMT+01:00 Mark De Wit <***@iesve.com>:
> > I have an application based on qt-solutions qtwinmigrate sample.
> >
> > Because we're integrating Qt into an existing MFC application, we're not
> > even running QApplication exec. The application uses MFC's entry point
> > for startup and drives the Qt event loop manually as part of the MFC
> > event loop.
> >
> > Mark
>
> I also did something like that on Linux with a software written with
> another graphical framework.
> We made it work by calling QApplication::processEvents() in the other
> framework event loop.

Both cases are served by integrating the event loop of the foreign framework
with Qt's. Doesn't matter how you start it (though I certainly prefer Qt's
app.exec()), but you need to integrate.

processEvents() is not a solution. It's, at best, a crude hack.

--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
Morten Sorvig
2016-12-12 21:14:52 UTC
Permalink
> On 10 Dec 2016, at 01:43, Thiago Macieira <***@intel.com> wrote:
>
> Em sexta-feira, 9 de dezembro de 2016, às 16:50:29 PST, Matthew Woehlke
> escreveu:
>> On 2016-12-09 16:23, Thiago Macieira wrote:
>>> Em sexta-feira, 9 de dezembro de 2016, às 15:28:13 PST, Matthew Woehlke
>>>
>>> escreveu:
>>>> I can work around that, though it's obnoxious. I'm more concerned about
>>>> not being able to tinker with the CLI arguments before Qt gets them.
>>>
>>> That's a valid concern, but not one that warrants a QApplication subclass.
>>
>> Right; that one is an issue if the user is no longer in control of
>> instantiating the Q*Application instance.
>
> Ah, that's a good point.
>
> Though quite frankly I don't see that as an issue. Applications can only have
> access to argc and argv if they write the main() function, which means they
> can continue to use the current functionality.
>
> I'm imaginiing that this new way is needed for platforms where a main()
> function makes no sense, in which case there's no command-line to begin with.

That is one use case, another is where the standard way to start the native
platform and event loop is not compatible with the Q*Application on stack and
app.exec() pattern. (See macOS example in the other mail)

Morten
Matthew Woehlke
2016-12-14 20:35:20 UTC
Permalink
On 2016-12-09 19:43, Thiago Macieira wrote:
> Em sexta-feira, 9 de dezembro de 2016, às 16:50:29 PST, Matthew Woehlke escreveu:
>> On 2016-12-09 16:23, Thiago Macieira wrote:
>>> That's a valid concern, but not one that warrants a QApplication subclass.
>>
>> Right; that one is an issue if the user is no longer in control of
>> instantiating the Q*Application instance.
>
> Ah, that's a good point.
>
> Though quite frankly I don't see that as an issue. Applications can only have
> access to argc and argv if they write the main() function, which means they
> can continue to use the current functionality.
>
> I'm imaginiing that this new way is needed for platforms where a main()
> function makes no sense, in which case there's no command-line to begin with.

If we're not deprecating the traditional main(), that WFM. (That's not
how I read the initial post, however...)

--
Matthew
Mathias Hasselmann
2016-12-12 18:53:50 UTC
Permalink
Hi,

Seems this turned into a nice bike shed discussion quickly, so let me
use the chance to present my preferred Qt main(). I am totally convinced
that this one should rule the Qt world:

class BlueBikeShedApplication : public QApplication
{
Q_OBJECT

public:
using QApplication::QApplication;

int run()
{
if (!parseCommandLine())
return EXIT_FAILURE;
if (!initializeColorBucket())
return EXIT_FAILURE;

setupBrush();

return exec();
}
};

int main(int argc, char *argv[])
{
return BlueBikeShedApplication{argc, argv}.run();
}

The big advantage I see in this approach is, that you work within a
proper QObject context with fully setup QApplication early. Also this
main() is sufficiently generic to be hidden in a platform specific
macro, or static library.

Thank you for reading,
Mathias
Simon Hausmann
2016-12-13 09:36:54 UTC
Permalink
Hi,


The joke of the bikeshedding aside I for one do like the idea of exporting a QObject sub-class instead of a function. That makes it easier to extend in the future with more entry-points as slots for example.




Simon

________________________________
From: Development <development-bounces+simon.hausmann=***@qt-project.org> on behalf of Mathias Hasselmann <***@taschenorakel.de>
Sent: Monday, December 12, 2016 7:53:50 PM
To: ***@qt-project.org
Subject: Re: [Development] A new approach for Qt main()

Hi,

Seems this turned into a nice bike shed discussion quickly, so let me
use the chance to present my preferred Qt main(). I am totally convinced
that this one should rule the Qt world:

class BlueBikeShedApplication : public QApplication
{
Q_OBJECT

public:
using QApplication::QApplication;

int run()
{
if (!parseCommandLine())
return EXIT_FAILURE;
if (!initializeColorBucket())
return EXIT_FAILURE;

setupBrush();

return exec();
}
};

int main(int argc, char *argv[])
{
return BlueBikeShedApplication{argc, argv}.run();
}

The big advantage I see in this approach is, that you work within a
proper QObject context with fully setup QApplication early. Also this
main() is sufficiently generic to be hidden in a platform specific
macro, or static library.

Thank you for reading,
Mathias
Laszlo Agocs
2016-12-13 09:42:05 UTC
Permalink
Hi,

How does this handle the cases that need code before the QGuiApplication construction? AFAICS it does not.

Laszlo

From: Development [mailto:development-bounces+laszlo.agocs=***@qt-project.org] On Behalf Of Simon Hausmann
Sent: Tuesday, December 13, 2016 10:37 AM
To: Mathias Hasselmann <***@taschenorakel.de>; ***@qt-project.org
Subject: Re: [Development] A new approach for Qt main()


Hi,



The joke of the bikeshedding aside I for one do like the idea of exporting a QObject sub-class instead of a function. That makes it easier to extend in the future with more entry-points as slots for example.







Simon

________________________________
From: Development <development-bounces+simon.hausmann=***@qt-project.org<mailto:development-bounces+simon.hausmann=***@qt-project.org>> on behalf of Mathias Hasselmann <***@taschenorakel.de<mailto:***@taschenorakel.de>>
Sent: Monday, December 12, 2016 7:53:50 PM
To: ***@qt-project.org<mailto:***@qt-project.org>
Subject: Re: [Development] A new approach for Qt main()

Hi,

Seems this turned into a nice bike shed discussion quickly, so let me
use the chance to present my preferred Qt main(). I am totally convinced
that this one should rule the Qt world:

class BlueBikeShedApplication : public QApplication
{
Q_OBJECT

public:
using QApplication::QApplication;

int run()
{
if (!parseCommandLine())
return EXIT_FAILURE;
if (!initializeColorBucket())
return EXIT_FAILURE;

setupBrush();

return exec();
}
};

int main(int argc, char *argv[])
{
return BlueBikeShedApplication{argc, argv}.run();
}

The big advantage I see in this approach is, that you work within a
proper QObject context with fully setup QApplication early. Also this
main() is sufficiently generic to be hidden in a platform specific
macro, or static library.

Thank you for reading,
Mathias
Simon Hausmann
2016-12-13 10:24:48 UTC
Permalink
Hi,


I don't think it does handle those cases. But we're not talking about eliminating main(), we're talking about a second supported "launch" method.


That said, it's still possible to run code before the constructor, although it's not pretty.


Simon

________________________________
From: Laszlo Agocs
Sent: Tuesday, December 13, 2016 10:42:05 AM
To: Simon Hausmann; Mathias Hasselmann; ***@qt-project.org
Subject: RE: [Development] A new approach for Qt main()

Hi,

How does this handle the cases that need code before the QGuiApplication construction? AFAICS it does not.

Laszlo

From: Development [mailto:development-bounces+laszlo.agocs=***@qt-project.org] On Behalf Of Simon Hausmann
Sent: Tuesday, December 13, 2016 10:37 AM
To: Mathias Hasselmann <***@taschenorakel.de>; ***@qt-project.org
Subject: Re: [Development] A new approach for Qt main()


Hi,



The joke of the bikeshedding aside I for one do like the idea of exporting a QObject sub-class instead of a function. That makes it easier to extend in the future with more entry-points as slots for example.







Simon

________________________________
From: Development <development-bounces+simon.hausmann=***@qt-project.org<mailto:development-bounces+simon.hausmann=***@qt-project.org>> on behalf of Mathias Hasselmann <***@taschenorakel.de<mailto:***@taschenorakel.de>>
Sent: Monday, December 12, 2016 7:53:50 PM
To: ***@qt-project.org<mailto:***@qt-project.org>
Subject: Re: [Development] A new approach for Qt main()

Hi,

Seems this turned into a nice bike shed discussion quickly, so let me
use the chance to present my preferred Qt main(). I am totally convinced
that this one should rule the Qt world:

class BlueBikeShedApplication : public QApplication
{
Q_OBJECT

public:
using QApplication::QApplication;

int run()
{
if (!parseCommandLine())
return EXIT_FAILURE;
if (!initializeColorBucket())
return EXIT_FAILURE;

setupBrush();

return exec();
}
};

int main(int argc, char *argv[])
{
return BlueBikeShedApplication{argc, argv}.run();
}

The big advantage I see in this approach is, that you work within a
proper QObject context with fully setup QApplication early. Also this
main() is sufficiently generic to be hidden in a platform specific
macro, or static library.

Thank you for reading,
Mathias
Simon Hausmann
2016-12-13 10:25:58 UTC
Permalink
Apologies, I should've expanded a little more on what I said. For example if we expose a QObject class to Qt instead of a function, then we could dispatch a static meta-call to a static initialization function that is called before the constructor, if present. Introspection makes that quite easy I think.



Simon

________________________________
From: Simon Hausmann
Sent: Tuesday, December 13, 2016 11:24:48 AM
To: Laszlo Agocs; Mathias Hasselmann; ***@qt-project.org
Subject: Re: [Development] A new approach for Qt main()


Hi,


I don't think it does handle those cases. But we're not talking about eliminating main(), we're talking about a second supported "launch" method.


That said, it's still possible to run code before the constructor, although it's not pretty.


Simon

________________________________
From: Laszlo Agocs
Sent: Tuesday, December 13, 2016 10:42:05 AM
To: Simon Hausmann; Mathias Hasselmann; ***@qt-project.org
Subject: RE: [Development] A new approach for Qt main()

Hi,

How does this handle the cases that need code before the QGuiApplication construction? AFAICS it does not.

Laszlo

From: Development [mailto:development-bounces+laszlo.agocs=***@qt-project.org] On Behalf Of Simon Hausmann
Sent: Tuesday, December 13, 2016 10:37 AM
To: Mathias Hasselmann <***@taschenorakel.de>; ***@qt-project.org
Subject: Re: [Development] A new approach for Qt main()


Hi,



The joke of the bikeshedding aside I for one do like the idea of exporting a QObject sub-class instead of a function. That makes it easier to extend in the future with more entry-points as slots for example.







Simon

________________________________
From: Development <development-bounces+simon.hausmann=***@qt-project.org<mailto:development-bounces+simon.hausmann=***@qt-project.org>> on behalf of Mathias Hasselmann <***@taschenorakel.de<mailto:***@taschenorakel.de>>
Sent: Monday, December 12, 2016 7:53:50 PM
To: ***@qt-project.org<mailto:***@qt-project.org>
Subject: Re: [Development] A new approach for Qt main()

Hi,

Seems this turned into a nice bike shed discussion quickly, so let me
use the chance to present my preferred Qt main(). I am totally convinced
that this one should rule the Qt world:

class BlueBikeShedApplication : public QApplication
{
Q_OBJECT

public:
using QApplication::QApplication;

int run()
{
if (!parseCommandLine())
return EXIT_FAILURE;
if (!initializeColorBucket())
return EXIT_FAILURE;

setupBrush();

return exec();
}
};

int main(int argc, char *argv[])
{
return BlueBikeShedApplication{argc, argv}.run();
}

The big advantage I see in this approach is, that you work within a
proper QObject context with fully setup QApplication early. Also this
main() is sufficiently generic to be hidden in a platform specific
macro, or static library.

Thank you for reading,
Mathias
Continue reading on narkive:
Loading...