Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Getting application startup to call main()
Qt 6.11 is out! See what's new in the release blog

Getting application startup to call main()

Scheduled Pinned Locked Moved Unsolved General and Desktop
12 Posts 4 Posters 5.3k Views 3 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • PerdrixP Perdrix

    I'm converting an application from MFC to Qt.

    I just replaced

    int WINAPI _tWinMain(
    	[[maybe_unused]] HINSTANCE hInstance,  // handle to current instance
    	[[maybe_unused]] HINSTANCE hPrevInstance,  // handle to previous instance
    	[[maybe_unused]] LPTSTR lpCmdLine,      // pointer to command line
    	[[maybe_unused]] int nCmdShow          // show state of window
    				   )
    

    in the main startup cpp file with a regular:

    int main(int argc, char* argv[])
    

    But when I try to run it the code throws an exception in Microsoft's winmain.cpp function AfxWinMain()

    Which means it's not picking up something I need to divert the call to my "old style" main().

    Probably something in one of the Qt libraries ( the qtentrypoint_win stuff)?

    Qt Modules is set to core;gui;gui-private;widgets;network

    What did I fail to do ?

    Thanks, David

    JonBJ Offline
    JonBJ Offline
    JonB
    wrote on last edited by JonB
    #2

    @Perdrix
    Well, yes, it would, because an MFC program calls AfxWinMain() and that requires int WINAPI _tWinMain(). You need to remove the MFC stuff (completely, and stop linking against MFC libraries) before this issue will go away.

    JonBJ 1 Reply Last reply
    2
    • PerdrixP Perdrix

      I'm converting an application from MFC to Qt.

      I just replaced

      int WINAPI _tWinMain(
      	[[maybe_unused]] HINSTANCE hInstance,  // handle to current instance
      	[[maybe_unused]] HINSTANCE hPrevInstance,  // handle to previous instance
      	[[maybe_unused]] LPTSTR lpCmdLine,      // pointer to command line
      	[[maybe_unused]] int nCmdShow          // show state of window
      				   )
      

      in the main startup cpp file with a regular:

      int main(int argc, char* argv[])
      

      But when I try to run it the code throws an exception in Microsoft's winmain.cpp function AfxWinMain()

      Which means it's not picking up something I need to divert the call to my "old style" main().

      Probably something in one of the Qt libraries ( the qtentrypoint_win stuff)?

      Qt Modules is set to core;gui;gui-private;widgets;network

      What did I fail to do ?

      Thanks, David

      Chris KawaC Offline
      Chris KawaC Offline
      Chris Kawa
      Lifetime Qt Champion
      wrote on last edited by Chris Kawa
      #3

      @Perdrix Windows apps can be compiled as console or windows subsystem.
      When compiled as console app the default entry point is the classic main function. When compiled as windows subsystem the default entry point is either WinMain or wWinMain, depending on whether you compile as UNICODE or not. _tWinMain is just a define that translates to either of those two.

      MFC provides an implementation of _tWinMain in its appmodule.cpp. It calls AfxWinMain to initialize MFC app instance. So long as you're linking to MFC libraries it will be included in your app.

      Qt provides an implementation of both WinMain and wWinMain that simply calls the classic main, so that it works the same for console and windows subsystems. In Qt6 this is provided via Qt6EntryPoint lib that you have to link to.

      But since both frameworks provide WinMain you can't use that as long as you link to both, because you'll have multiple conflicting definitions.

      As a workaround for the time you're porting you can manually specify the entry point in the linker settings. Go to project properties -> Linker -> Advanced -> Entry Point and type mainCRTStartup in there. This will cause the app to use the classic main as a startup point and ignore the WinMain provided by MFC.
      When you're done porting remove that override, remove linking to MFC and link to Qt6EntryPoint.

      Btw. don't modify the winmain.cpp or appmodul.cpp files. Those are internal MFC files that should not be touched.

      PerdrixP 1 Reply Last reply
      3
      • Chris KawaC Chris Kawa

        @Perdrix Windows apps can be compiled as console or windows subsystem.
        When compiled as console app the default entry point is the classic main function. When compiled as windows subsystem the default entry point is either WinMain or wWinMain, depending on whether you compile as UNICODE or not. _tWinMain is just a define that translates to either of those two.

        MFC provides an implementation of _tWinMain in its appmodule.cpp. It calls AfxWinMain to initialize MFC app instance. So long as you're linking to MFC libraries it will be included in your app.

        Qt provides an implementation of both WinMain and wWinMain that simply calls the classic main, so that it works the same for console and windows subsystems. In Qt6 this is provided via Qt6EntryPoint lib that you have to link to.

        But since both frameworks provide WinMain you can't use that as long as you link to both, because you'll have multiple conflicting definitions.

        As a workaround for the time you're porting you can manually specify the entry point in the linker settings. Go to project properties -> Linker -> Advanced -> Entry Point and type mainCRTStartup in there. This will cause the app to use the classic main as a startup point and ignore the WinMain provided by MFC.
        When you're done porting remove that override, remove linking to MFC and link to Qt6EntryPoint.

        Btw. don't modify the winmain.cpp or appmodul.cpp files. Those are internal MFC files that should not be touched.

        PerdrixP Offline
        PerdrixP Offline
        Perdrix
        wrote on last edited by Perdrix
        #4

        @Chris-Kawa Well here's the strange thing. One of my projects which I converted a long time back has a startup call stack that looks like this:

        DeepSkyStacker.exe!main(int argc, char * * argv) Line 904
        	at C:\Users\amonra\Documents\GitHub\DSS\DeepSkyStacker\DeepSkyStacker.cpp(904)
        DeepSkyStacker.exe!WinMain(HINSTANCE__ * __formal, HINSTANCE__ * __formal, char * __formal, int __formal) Line 50
        	at C:\Users\qt\work\qt\qtbase\src\entrypoint\qtentrypoint_win.cpp(50)
        DeepSkyStacker.exe!invoke_main() Line 107
        	at D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl(107)
        DeepSkyStacker.exe!__scrt_common_main_seh() Line 288
        	at D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl(288)
        DeepSkyStacker.exe!__scrt_common_main() Line 331
        	at D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl(331)
        DeepSkyStacker.exe!WinMainCRTStartup(void * __formal) Line 17
        	at D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_winmain.cpp(17)
        kernel32.dll!BaseThreadInitThunk()
        ntdll.dll!RtlUserThreadStart()
        

        The one I am currently trying to convert has call stack up to the point of failure that looks like:

        mfc140ud.dll!AfxWinMain(HINSTANCE__ * hInstance, HINSTANCE__ * hPrevInstance, wchar_t * lpCmdLine, int nCmdShow) Line 37
        	at D:\a\_work\1\s\src\vctools\VC7Libs\Ship\ATLMFC\Src\MFC\winmain.cpp(37)
        DeepSkyStackerLive.exe!wWinMain(HINSTANCE__ * hInstance, HINSTANCE__ * hPrevInstance, wchar_t * lpCmdLine, int nCmdShow) Line 26
        	at D:\a\_work\1\s\src\vctools\VC7Libs\Ship\ATLMFC\Src\MFC\appmodul.cpp(26)
        DeepSkyStackerLive.exe!invoke_main() Line 123
        	at D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl(123)
        DeepSkyStackerLive.exe!__scrt_common_main_seh() Line 288
        	at D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl(288)
        DeepSkyStackerLive.exe!__scrt_common_main() Line 331
        	at D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl(331)
        DeepSkyStackerLive.exe!wWinMainCRTStartup(void * __formal) Line 17
        	at D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_wwinmain.cpp(17)
        kernel32.dll!BaseThreadInitThunk()
        ntdll.dll!RtlUserThreadStart()
        

        So clearly I must have done something to get the first one working!

        Note that I didn't override the Entry Point in the 1st of these projects

        JonBJ 1 Reply Last reply
        0
        • PerdrixP Perdrix

          @Chris-Kawa Well here's the strange thing. One of my projects which I converted a long time back has a startup call stack that looks like this:

          DeepSkyStacker.exe!main(int argc, char * * argv) Line 904
          	at C:\Users\amonra\Documents\GitHub\DSS\DeepSkyStacker\DeepSkyStacker.cpp(904)
          DeepSkyStacker.exe!WinMain(HINSTANCE__ * __formal, HINSTANCE__ * __formal, char * __formal, int __formal) Line 50
          	at C:\Users\qt\work\qt\qtbase\src\entrypoint\qtentrypoint_win.cpp(50)
          DeepSkyStacker.exe!invoke_main() Line 107
          	at D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl(107)
          DeepSkyStacker.exe!__scrt_common_main_seh() Line 288
          	at D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl(288)
          DeepSkyStacker.exe!__scrt_common_main() Line 331
          	at D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl(331)
          DeepSkyStacker.exe!WinMainCRTStartup(void * __formal) Line 17
          	at D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_winmain.cpp(17)
          kernel32.dll!BaseThreadInitThunk()
          ntdll.dll!RtlUserThreadStart()
          

          The one I am currently trying to convert has call stack up to the point of failure that looks like:

          mfc140ud.dll!AfxWinMain(HINSTANCE__ * hInstance, HINSTANCE__ * hPrevInstance, wchar_t * lpCmdLine, int nCmdShow) Line 37
          	at D:\a\_work\1\s\src\vctools\VC7Libs\Ship\ATLMFC\Src\MFC\winmain.cpp(37)
          DeepSkyStackerLive.exe!wWinMain(HINSTANCE__ * hInstance, HINSTANCE__ * hPrevInstance, wchar_t * lpCmdLine, int nCmdShow) Line 26
          	at D:\a\_work\1\s\src\vctools\VC7Libs\Ship\ATLMFC\Src\MFC\appmodul.cpp(26)
          DeepSkyStackerLive.exe!invoke_main() Line 123
          	at D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl(123)
          DeepSkyStackerLive.exe!__scrt_common_main_seh() Line 288
          	at D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl(288)
          DeepSkyStackerLive.exe!__scrt_common_main() Line 331
          	at D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl(331)
          DeepSkyStackerLive.exe!wWinMainCRTStartup(void * __formal) Line 17
          	at D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_wwinmain.cpp(17)
          kernel32.dll!BaseThreadInitThunk()
          ntdll.dll!RtlUserThreadStart()
          

          So clearly I must have done something to get the first one working!

          Note that I didn't override the Entry Point in the 1st of these projects

          JonBJ Offline
          JonBJ Offline
          JonB
          wrote on last edited by JonB
          #5

          @Perdrix
          The first one you already got as far as (from invoke_main()):

          at C:\Users\qt\work\qt\qtbase\src\entrypoint\qtentrypoint_win.cpp(50)

          The second one still has at same point:

          at D:\a\_work\1\s\src\vctools\VC7Libs\Ship\ATLMFC\Src\MFC\appmodul.cpp(26)

          So the first one has been moved to Qt, the second one is still MFC.

          You don't need to "override entry points" once you (fully) move from MFC to Qt.

          PerdrixP 1 Reply Last reply
          0
          • JonBJ JonB

            @Perdrix
            The first one you already got as far as (from invoke_main()):

            at C:\Users\qt\work\qt\qtbase\src\entrypoint\qtentrypoint_win.cpp(50)

            The second one still has at same point:

            at D:\a\_work\1\s\src\vctools\VC7Libs\Ship\ATLMFC\Src\MFC\appmodul.cpp(26)

            So the first one has been moved to Qt, the second one is still MFC.

            You don't need to "override entry points" once you (fully) move from MFC to Qt.

            PerdrixP Offline
            PerdrixP Offline
            Perdrix
            wrote on last edited by Perdrix
            #6

            @JonB That's the whole issue! I have no MFC GUI code left in that source tree, so I want to be fully moved over to Qt. There are a few Windows calls that notionally might qualify as MFC but...

            1 Reply Last reply
            0
            • JonBJ JonB

              @Perdrix
              Well, yes, it would, because an MFC program calls AfxWinMain() and that requires int WINAPI _tWinMain(). You need to remove the MFC stuff (completely, and stop linking against MFC libraries) before this issue will go away.

              JonBJ Offline
              JonBJ Offline
              JonB
              wrote on last edited by
              #7

              @Perdrix

              @JonB said in Getting application startup to call main():

              You need to remove the MFC stuff (completely, and stop linking against MFC libraries) before this issue will go away.

              Did you remove linking against MFC libraries? Because the traceback starts with mfc140ud.dll!AfxWinMain....

              PerdrixP 1 Reply Last reply
              1
              • JonBJ JonB

                @Perdrix

                @JonB said in Getting application startup to call main():

                You need to remove the MFC stuff (completely, and stop linking against MFC libraries) before this issue will go away.

                Did you remove linking against MFC libraries? Because the traceback starts with mfc140ud.dll!AfxWinMain....

                PerdrixP Offline
                PerdrixP Offline
                Perdrix
                wrote on last edited by
                #8

                @JonB I needed to define _AFXDLL

                JonBJ 1 Reply Last reply
                0
                • PerdrixP Perdrix

                  @JonB I needed to define _AFXDLL

                  JonBJ Offline
                  JonBJ Offline
                  JonB
                  wrote on last edited by JonB
                  #9

                  @Perdrix
                  I cannot imagine why, you have a program which (according to you) has no vestiges of MFC left and has nothing to do with MFC. Why you would then need to define _AFXDLL, in order to compile/link any program you write which has nothing to do with MFC, is quite beyond me....

                  1 Reply Last reply
                  2
                  • Chris KawaC Offline
                    Chris KawaC Offline
                    Chris Kawa
                    Lifetime Qt Champion
                    wrote on last edited by
                    #10

                    As @JonB said, if you're done with MFC you need to remove linking against its libraries. That's where the appmodul.cpp comes from in your callstack. Defining _AFXDLL is not a proper solution. It just marks your app as a standalone MFC module so that it does not declare global state in it. It does not remove MFC from your app.
                    Go to your project settings and in the Advanced section disable MFC in the "Use MFC" field.

                    1 Reply Last reply
                    3
                    • W Offline
                      W Offline
                      woldie
                      wrote on last edited by
                      #11

                      hello @Perdrix , @Chris-Kawa
                      could anybody provide some example code? It is hard for me to get a bare MFC test project running with Qt6.
                      I have the linker settings to MFC DLL. How would look like wWinMain with MyMfcApp theApp?

                      1 Reply Last reply
                      0
                      • PerdrixP Offline
                        PerdrixP Offline
                        Perdrix
                        wrote on last edited by
                        #12

                        You may wish to download the source code for DeepSkyStacker 5.1.0 which was first released step in the journey from MFC to Qt (5.1.0 is a hybrid). You can DL the source code from here: https://github.com/deepskystacker/DSS/archive/refs/tags/5.1.0.zip.

                        The file of interest is DeepSkyStacker\DeepSkyStacker.cpp

                        HtH
                        David

                        1 Reply Last reply
                        0

                        • Login

                        • Login or register to search.
                        • First post
                          Last post
                        0
                        • Categories
                        • Recent
                        • Tags
                        • Popular
                        • Users
                        • Groups
                        • Search
                        • Get Qt Extensions
                        • Unsolved