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()
Forum Updated to NodeBB v4.3 + New Features

Getting application startup to call main()

Scheduled Pinned Locked Moved Unsolved General and Desktop
12 Posts 4 Posters 3.5k 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 Offline
    PerdrixP Offline
    Perdrix
    wrote on last edited by Perdrix
    #1

    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 Chris KawaC 2 Replies Last reply
    0
    • 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 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 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