Plasma Engine  2.0
Loading...
Searching...
No Matches
ApplicationEntryPoint_win.h
1
2#pragma once
3
5
6#include <Foundation/Basics/Platform/Win/MinWindows.h>
7#include <Foundation/Logging/Log.h>
8#include <Foundation/Memory/MemoryTracker.h>
9#include <Foundation/Threading/Lock.h>
10#include <Foundation/Threading/Mutex.h>
11
12namespace plApplicationDetails
13{
14 PL_FOUNDATION_DLL void SetConsoleCtrlHandler(plMinWindows::BOOL(PL_WINDOWS_WINAPI* consoleHandler)(plMinWindows::DWORD dwCtrlType));
15 PL_FOUNDATION_DLL plMutex& GetShutdownMutex();
16
17 template <typename AppClass, typename... Args>
18 int ConsoleEntry(int iArgc, const char** pArgv, Args&&... arguments)
19 {
20#if PL_ENABLED(PL_COMPILER_MSVC) // Internal compiler error in MSVC. Can not align buffer otherwise the compiler will crash.
21 static char appBuffer[sizeof(AppClass)]; // Not on the stack to cope with smaller stacks.
22#else
23 alignas(PL_ALIGNMENT_OF(AppClass)) static char appBuffer[sizeof(AppClass)]; // Not on the stack to cope with smaller stacks.
24#endif
25
26 // This mutex will prevent the console shutdown handler to return
27 // as long as this entry point is not finished executing
28 // (see consoleHandler below).
29 PL_LOCK(GetShutdownMutex());
30
31 static AppClass* pApp = new (appBuffer) AppClass(std::forward<Args>(arguments)...);
32 pApp->SetCommandLineArguments((plUInt32)iArgc, pArgv);
33
34 // This handler overrides the default handler
35 // (which would call ExitProcess, which leads to disorderly engine shutdowns)
36 const auto consoleHandler = [](plMinWindows::DWORD ctrlType) -> plMinWindows::BOOL
37 {
38 // We have to wait until the application has shut down orderly
39 // since Windows will kill everything after this handler returns
40 pApp->SetReturnCode(ctrlType);
41 pApp->RequestQuit();
42 PL_LOCK(GetShutdownMutex());
43 return 1; // returns TRUE, which deactivates the default console control handler
44 };
45 SetConsoleCtrlHandler(consoleHandler);
46
47 plRun(pApp); // Life cycle & run method calling
48
49 const int iReturnCode = pApp->GetReturnCode();
50 if (iReturnCode != 0)
51 {
52 std::string text = pApp->TranslateReturnCode();
53 if (!text.empty())
54 plLog::Printf("Return Code: %i = '%s'\n", iReturnCode, text.c_str());
55 else
56 plLog::Printf("Return Code: %i\n", iReturnCode, text.c_str());
57 }
58
59 const bool memLeaks = pApp->IsMemoryLeakReportingEnabled();
60 pApp->~AppClass();
61 memset((void*)pApp, 0, sizeof(AppClass));
62 if (memLeaks)
64
65 return iReturnCode;
66 }
67
68 template <typename AppClass, typename... Args>
69 int ApplicationEntry(Args&&... arguments)
70 {
71#if PL_ENABLED(PL_COMPILER_MSVC) // Internal compiler error in MSVC. Can not align buffer otherwise the compiler will crash.
72 static char appBuffer[sizeof(AppClass)]; // Not on the stack to cope with smaller stacks.
73#else
74 alignas(PL_ALIGNMENT_OF(AppClass)) static char appBuffer[sizeof(AppClass)]; // Not on the stack to cope with smaller stacks.
75#endif
76
77 AppClass* pApp = new (appBuffer) AppClass(std::forward<Args>(arguments)...);
78 pApp->SetCommandLineArguments((plUInt32)__argc, const_cast<const char**>(__argv));
79 plRun(pApp); // Life cycle & run method calling
80
81 const int iReturnCode = pApp->GetReturnCode();
82 if (iReturnCode != 0)
83 {
84 std::string text = pApp->TranslateReturnCode();
85 if (!text.empty())
86 plLog::Printf("Return Code: '%s'\n", text.c_str());
87 }
88
89 const bool memLeaks = pApp->IsMemoryLeakReportingEnabled();
90 pApp->~AppClass();
91 memset((void*)pApp, 0, sizeof(AppClass));
92 if (memLeaks)
94
95 return iReturnCode;
96 }
97} // namespace plApplicationDetails
98
100#define PL_CONSOLEAPP_ENTRY_POINT(AppClass, ...) \
101 /* Enables that on machines with multiple GPUs the NVIDIA / AMD GPU is preferred */ \
102 extern "C" \
103 { \
104 _declspec(dllexport) plMinWindows::DWORD NvOptimusEnablement = 0x00000001; \
105 _declspec(dllexport) plMinWindows::DWORD AmdPowerXpressRequestHighPerformance = 0x00000001; \
106 } \
107 PL_APPLICATION_ENTRY_POINT_CODE_INJECTION \
108 int main(int argc, const char** argv) \
109 { \
110 return plApplicationDetails::ConsoleEntry<AppClass>(argc, argv, __VA_ARGS__); \
111 }
112
113// If windows.h is already included use the native types, otherwise use types from plMinWindows
114//
115// In PL_APPLICATION_ENTRY_POINT we use macro magic to concatenate strings in such a way that depending on whether windows.h has
116// been included in the mean time, either the macro is chosen which expands to the proper Windows.h type
117// or the macro that expands to our plMinWindows type.
118// Unfortunately we cannot do the decision right here, as Windows.h may not yet be included, but may get included later.
119#define _PL_APPLICATION_ENTRY_POINT_HINSTANCE HINSTANCE
120#define _PL_APPLICATION_ENTRY_POINT_LPSTR LPSTR
121#define _PL_APPLICATION_ENTRY_POINT_HINSTANCE_WINDOWS_ plMinWindows::HINSTANCE
122#define _PL_APPLICATION_ENTRY_POINT_LPSTR_WINDOWS_ plMinWindows::LPSTR
123
124#ifndef _In_
125# define UndefSAL
126# define _In_
127# define _In_opt_
128#endif
129
134#define PL_APPLICATION_ENTRY_POINT(AppClass, ...) \
135 /* Enables that on machines with multiple GPUs the NVIDIA / AMD GPU is preferred */ \
136 extern "C" \
137 { \
138 _declspec(dllexport) plMinWindows::DWORD NvOptimusEnablement = 0x00000001; \
139 _declspec(dllexport) plMinWindows::DWORD AmdPowerXpressRequestHighPerformance = 0x00000001; \
140 } \
141 PL_APPLICATION_ENTRY_POINT_CODE_INJECTION \
142 int PL_WINDOWS_CALLBACK WinMain(_In_ PL_PP_CONCAT(_PL_, PL_PP_CONCAT(APPLICATION_ENTRY_POINT_HINSTANCE, _WINDOWS_)) hInstance, \
143 _In_opt_ PL_PP_CONCAT(_PL_, PL_PP_CONCAT(APPLICATION_ENTRY_POINT_HINSTANCE, _WINDOWS_)) hPrevInstance, \
144 _In_ PL_PP_CONCAT(_PL_, PL_PP_CONCAT(APPLICATION_ENTRY_POINT_LPSTR, _WINDOWS_)) lpCmdLine, _In_ int nCmdShow) \
145 { \
146 return plApplicationDetails::ApplicationEntry<AppClass>(__VA_ARGS__); \
147 }
148
149#ifdef UndefSAL
150# undef _In_
151# undef _In_opt_
152#endif
static void Printf(const char *szFormat,...)
Calls low-level OS functionality to print a string to the typical outputs. Forwards to Print.
Definition Log.cpp:271
static void DumpMemoryLeaks()
Prints the known memory leaks to plLog and triggers an assert if there are any.
Definition MemoryTracker.cpp:470
Provides a simple mechanism for mutual exclusion to prevent multiple threads from accessing a shared ...
Definition Mutex.h:13