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}VisualCWin32Debug
21 ${SDL2_ROOT}VisualCWin32Release
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}VisualCWin32Debug
  • “配置”:”Release”--->“”链接器“--->”常规”--->”附加库目录“: ${SDL2_ROOT}VisualCWin32Release
  • 拷贝对应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()函数?

 

原文地址:https://www.cnblogs.com/bluebeecoder/p/13744463.html