SDL2使用VS C++應用入門及入口點函數


 

自上篇文章所述在VS C++生成SDL2庫文件,編寫簡單Hello World程序驗證庫文件。

 

1、使用Visual Studio 2019 創建一個終端控制台程序。

點擊“文件—新建—項目”,選擇“控制台應用”,輸入源代碼:

 test.cpp:

 1 #include <iostream>
 2 #include <SDL.h>
 3 
 4 /*
 5  * Lesson 0: Test to make sure SDL is setup properly  6  */
 7 int main(int, char**) {  8     if (SDL_Init(SDL_INIT_VIDEO) != 0) {  9         std::cout << "SDL_Init Error: " << SDL_GetError() << std::endl; 10         return 1; 11  } 12     std::cout << "SDL_Init OK!!!" << std::endl; 13  SDL_Quit(); 14 
15     return 0; 16 } 17 
18 /*
19 ${SDL2_ROOT}\include 20 ${SDL2_ROOT}\VisualC\Win32\Debug 21 ${SDL2_ROOT}\VisualC\Win32\Release 22 SDL2.lib 23 SDL2main.lib 24 */

 

2、設置庫文件目錄、依賴項目錄、依賴項文件名。

點擊菜單“項目“--->"屬性”,在“配置”欄中的“所有配置”適合debug和release都相同的設置,不相同設置單獨選擇”debug”或”release”配置。上述代碼中的${SDL2_ROOT} 替換為你本機實際目錄。

  • “配置”:“所有配置”--->“C/C++”--->“常規”--->“附加包含目錄” :${SDL2_ROOT}\include
  • “配置”:“所有配置”--->“”鏈接器“--->”輸入“--->”附加依賴項“: SDL2.lib、SDL2main.lib
  • “配置”:”Debug”--->“”鏈接器“--->”常規”--->”附加庫目錄“: ${SDL2_ROOT}\VisualC\Win32\Debug
  • “配置”:”Release”--->“”鏈接器“--->”常規”--->”附加庫目錄“: ${SDL2_ROOT}\VisualC\Win32\Release
  • 拷貝對應debug/release版本的SDL2.dll到對應EXE輸出目錄。

執行程序輸出結果,如圖:

     

 

3、補充說明:SDL2入口點函數(入口點符號)。

     

  Test.cpp::main() 中"main"已在頭文件SDL_main.h中定義為宏,跟蹤宏生效的依賴關系如下 :

    main ---> SDL_main.h::109 ---> SDL_main.h::40 SDL_MAIN_AVAILABLE ---> SDL_main.h::40 __WIN32__ ---> SDL_platform.h::153 __WINDOWS__ ---> SDL_platform.h::149 WINAPI_FAMILY_WINRT ---> SDL_platform.h:: 139 ---> (…) 

  Test.cpp 中"main"最終只會有兩種結果,而此示例代碼經過預處理后進行編譯前函數名實際為:SDL_main 。

 

    條件==true ---> SDL_main()

    條件==false ---> main()

 

   Test.cpp::main()不是程序的入口點函數,這是因WINDOWS平台C++程序對真實第一個入口點函數有定義,微軟官方文檔說明鏈接如下:

https://docs.microsoft.com/zh-cn/cpp/build/reference/entry-entry-point-symbol?view=vs-2019

 

  由此可見,可分三種情況有三類真正的程序第一個入口函數,再經過固定流程調用指定函數。通過調試本示例分析,得到調用Test.cpp::main() 的函數在SDL_windows_main.c文件,而SDL_windows_main.c::19 執行undef main。

 

 

 

 

 SDL_windows_main.c源代碼文件如下:

 1 /* Pop up an out of memory message, returns to Windows */
 2 static BOOL
 3 OutOfMemory(void)
 4 {
 5     SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Fatal Error", "Out of memory - aborting", NULL);
 6     return FALSE;
 7 }
 8 
 9 #if defined(_MSC_VER)
10 /* The VC++ compiler needs main/wmain defined */
11 # define console_ansi_main main
12 # if UNICODE
13 #  define console_wmain wmain
14 # endif
15 #endif
16 
17 /* Gets the arguments with GetCommandLine, converts them to argc and argv
18    and calls SDL_main */
19 static int
20 main_getcmdline(void)
21 {
22     LPWSTR *argvw;
23     char **argv;
24     int i, argc, result;
25 
26     argvw = CommandLineToArgvW(GetCommandLineW(), &argc);
27     if (argvw == NULL) {
28         return OutOfMemory();
29     }
30 
31     /* Parse it into argv and argc */
32     argv = (char **)SDL_calloc(argc + 1, sizeof(*argv));
33     if (!argv) {
34         return OutOfMemory();
35     }
36     for (i = 0; i < argc; ++i) {
37         argv[i] = WIN_WStringToUTF8(argvw[i]);
38         if (!argv[i]) {
39             return OutOfMemory();
40         }
41     }
42     argv[i] = NULL;
43     LocalFree(argvw);
44 
45     SDL_SetMainReady();
46 
47     /* Run the application main() code */
48     result = SDL_main(argc, argv);
49 
50     /* Free argv, to avoid memory leak */
51     for (i = 0; i < argc; ++i) {
52         SDL_free(argv[i]);
53     }
54     SDL_free(argv);
55 
56     return result;
57 }
58 
59 /* This is where execution begins [console apps, ansi] */
60 int
61 console_ansi_main(int argc, char *argv[])
62 {
63     return main_getcmdline();
64 }
65 
66 
67 #if UNICODE
68 /* This is where execution begins [console apps, unicode] */
69 int
70 console_wmain(int argc, wchar_t *wargv[], wchar_t *wenvp)
71 {
72     return main_getcmdline();
73 }
74 #endif
75 
76 /* This is where execution begins [windowed apps] */
77 int WINAPI
78 WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
79 {
80     return main_getcmdline();
81 }
82 
83 #endif /* __WIN32__ */
84 
85 /* vi: set ts=4 sw=4 expandtab: */

 SDL_windows_main.c源代碼經過預處理后,如下:

 1 static BOOL
 2 OutOfMemory(void)
 3 {
 4     SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Fatal Error", "Out of memory - aborting", ((void *)0));
 5     return 0;
 6 }
 7 
 8 static int
 9 main_getcmdline(void)
10 {
11     LPWSTR *argvw;
12     char **argv;
13     int i, argc, result;
14     argvw = CommandLineToArgvW(GetCommandLineW(), &argc);
15     if (argvw == ((void *)0)) {
16         return OutOfMemory();
17     }
18     argv = (char **)SDL_calloc(argc + 1, sizeof(*argv));
19     if (!argv) {
20         return OutOfMemory();
21     }
22     for (i = 0; i < argc; ++i) {
23         argv[i] = SDL_iconv_string("UTF-8", "UTF-16LE", (char *)(argvw[i]), (SDL_wcslen(argvw[i])+1)*sizeof(WCHAR));
24         if (!argv[i]) {
25             return OutOfMemory();
26         }
27     }
28     argv[i] = ((void *)0);
29     LocalFree(argvw);
30     SDL_SetMainReady();
31     result = SDL_main(argc, argv);
32     for (i = 0; i < argc; ++i) {
33         SDL_free(argv[i]);
34     }
35     SDL_free(argv);
36     return result;
37 }
38 int
39 main(int argc, char *argv[])
40 {
41     return main_getcmdline();
42 }
43 int
44 wmain(int argc, wchar_t *wargv[], wchar_t *wenvp)
45 {
46     return main_getcmdline();
47 }
48 
49 int __stdcall
50 WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
51 {
52     return main_getcmdline();
53 }

 

  經過以上分析后,大家有進一步理解了,本示例代碼是在WINDOWS平台下創建為控制台程序,程序是怎樣從入口點函數調用到應用層的Test.cpp::main()函數?

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM