为啥 SDL 定义主宏?

Posted

技术标签:

【中文标题】为啥 SDL 定义主宏?【英文标题】:Why SDL defines main macro?为什么 SDL 定义主宏? 【发布时间】:2012-08-12 03:33:56 【问题描述】:

在设置SDL遇到一些麻烦后,我发现SDL定义了一个宏来替换main:

#define main SDL_main

// And then
extern C_LINKAGE int SDL_main(int argc, char *argv[]);

如果主函数没有定义argcargv 参数,这也会产生编译错误。

这个宏一看到就头疼……为什么SDL需要重新定义main?经过一番搜索,我发现有人#undef main,并正常使用。

那么问题来了: 为什么 SDL 需要重新定义 main,它的作用是什么?取消定义有什么副作用吗?

我注意到的一件事是 SDL 将标准输出和错误重定向到文件(我不希望这种行为),如果我取消定义 main,这种行为就会停止。

【问题讨论】:

You can disable this behavior. 是的,这篇文章很愤怒。这样做的主要原因是对 Windows 上的不同入口点(winmain)和其他平台上的传统入口点(int main)进行抽象。它简化了许多原本需要 ifdef 或单独的源文件的代码。这是一种方便的机制,如果您愿意,可以手动完成。 【参考方案1】:

每the SDL Windows FAQ:

即使您正在创建 Windows 应用程序,您也应该使用 main() 而不是 WinMain(),因为 SDL 提供了 WinMain() 的一个版本,它在调用您的主代码之前执行一些 SDL 初始化。

如果由于某种原因您需要使用WinMain(),请查看src/main/win32/SDL_main.c 中的SDL 源代码,了解您需要在WinMain() 函数中进行何种初始化,以使SDL 正常工作。

SDL 需要初始化,因此它会注入自己的 main 函数,该函数会在调用“主”函数之前运行其初始化,并将其重命名为 SDL_main,这样它就不会与实际的 main 函数冲突。如常见问题解答中所述,您的 main 函数必须采用以下形式

int main(int argc, char* argv[])

【讨论】:

几乎每个库都需要初始化,但这看起来是一个不好的做法。无论如何 +1。 @DavidGrayson 的做法确实很糟糕,特别是如果你有两个库可以做到这一点...... patooty 的巨大痛苦 我可以编写自己的 main() 实现,而不是使用这个奇怪的 SDL_main() 函数吗?有些事情(例如,stdout 重定向)有点压在我的喉咙里,我不想要它。 同意大卫。该宏是一种 C 技术。 C++ 有许多明智的选择。 我不仅同意大卫的观点,认为这是一种糟糕的做法,而且 SDL 有自己的 SDL_init 初始化调用。据我记得,SDLmain 中的初始化非常无用(如果我记得,重定向控制台)【参考方案2】:

虽然我同意这是一种奇怪的做法,但在某些情况下这是一个合理的解决方案,尽管它在很大程度上取决于平台。考虑到不同的平台有不同的入口点。 Windows 通常是 WinMain,Linux 是主要的,与 android 的交互发生在 Java 中,WinRT 使用 C++/CX 扩展,等等。程序入口点和 API 可能非常特定于平台,SDL 试图为您省去处理这些问题的麻烦。如果您只针对 Windows 并且 SDL 只是为了省去您使用 WIN32 API 的麻烦,您可能不需要它。但是,如果您超越桌面,我认为您会发现它很有用。

【讨论】:

“超越桌面”——嘿! Linux 和 OsX 也是桌面的。 "Windows 通常是 WinMain" 在任何 MinGW 工具链上,您可以使用标准 C 或 C++ main,MinGW 将完成这项工作。

以上是关于为啥 SDL 定义主宏?的主要内容,如果未能解决你的问题,请参考以下文章

SDL_GetTicks() 定义缺失。 (SDL 2.0.3)

使用 CMake 对 SDL 的未定义引用

SDL1 -> 使用自定义屏幕模式类构建 SDL2 分辨率列表

SDL2 丢失 OpenGL 上下文或未定义函数

SDL2:LNK1561:必须定义入口点

XCode 4.3.2 SDLMain.o 中的 SDL 未定义符号