Getting application startup to call main()
-
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
-
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
-
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
@Perdrix Windows apps can be compiled as console or windows subsystem.
When compiled as console app the default entry point is the classicmain
function. When compiled as windows subsystem the default entry point is eitherWinMain
orwWinMain
, 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 itsappmodule.cpp
. It callsAfxWinMain
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
andwWinMain
that simply calls the classicmain
, 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 classicmain
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.
-
@Perdrix Windows apps can be compiled as console or windows subsystem.
When compiled as console app the default entry point is the classicmain
function. When compiled as windows subsystem the default entry point is eitherWinMain
orwWinMain
, 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 itsappmodule.cpp
. It callsAfxWinMain
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
andwWinMain
that simply calls the classicmain
, 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 classicmain
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.
@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
-
@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
@Perdrix
The first one you already got as far as (frominvoke_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.
-
@Perdrix
The first one you already got as far as (frominvoke_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.
-
@Perdrix
Well, yes, it would, because an MFC program callsAfxWinMain()
and that requiresint WINAPI _tWinMain()
. You need to remove the MFC stuff (completely, and stop linking against MFC libraries) before this issue will go away.@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
.... -
@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
.... -
@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.... -
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.