错误LNK2019:在函数___tmainCRTStartup中引用了未解决的外部符号_main,但这次不是Windows / Console问题!

38

所以,臭名昭著的错误又出现了。项目抱怨找不到main()方法(这就是该错误的意思,对吧)。

然而我确实有一个main,我的项目也是控制台项目,应该没问题。它之前可以运行,所以我知道不是这个问题。

此外,项目包含的类和文件太多,无法全部发布,因此如果需要,我会根据请求发布任何您需要的类。

这是一个在Visual Studio 2010上使用C++、OpenGL和SDL开发的游戏。它并不是任何库的问题,因为突然间出现了这个链接器错误,之前一切都好好的。

编辑:main()方法:

int main(int argc, char **argv)
{
 glutInit(&argc, argv);
 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH | GLUT_ALPHA);
 glutCreateWindow("Game");

 glEnable(GL_DEPTH_TEST);
 glEnable(GL_NORMALIZE);
 glEnable(GL_COLOR_MATERIAL);
 glEnable(GL_BLEND);
 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

 g = Game();
 glutInitWindowSize(g.getScreenWidth(), g.getScreenHeight());
 //glutPositionWindow(1280, 50);

 // Callbacks
 glutDisplayFunc(handleRedraw);
 glutReshapeFunc(handleResize);
 glutMouseFunc(handleMouseClicks);
 glutPassiveMotionFunc(handleMouseOvers);
 glutKeyboardFunc(handleKeyboardEvents);
 glutTimerFunc(50, moveItemToInventory, 0);

 glutMainLoop();

 return 0;
}

1
清理和重建项目没有帮助吗? - karlphillip
@karlphillip,没有尝试过很多次。 - OddCore
这是在你链接SDL之后开始发生的吗? - karlphillip
不,我之前已经实现了SDL。老实说,我不确定是什么导致了这个错误,因为自从它正常工作以来,我并没有做过任何极端的事情 - 只是改变了一些类的工作方式并添加了新的类。 - OddCore
4个回答

95

SDL_main.h会自动从SDL.h中包含进来,因此您总是会得到令人烦恼的 #define。

只需写:

#include <SDL.h>
#undef main

它应该可以正常工作。


我将这些代码放在我的类上面,但是出现了更多错误: 错误1:错误 LNK2005: _main 已在 Main.obj 中定义 错误2:错误 LNK2019: 无法解析的外部符号 "public: void __thiscall Simulation::simulate(void)" (?simulate@Simulation@@QAEXXZ),该符号在函数 _main 中被引用 错误3:错误 LNK2019: 无法解析的外部符号 _SDL_main,在函数 _main 中被引用所有在这里得到的帮助都没有起作用,我也尝试了其他所有方法,都没有成功... 请帮忙。 - Photonic
1
谢谢,对我有用!(而且那确实是一个奇怪的#define) - Viktor Sehr
10
理由在于您可以在正常系统(Linux、MacOS等)和Windows中使用相同的代码(int main() {...})。在Windows中,要想获得一个没有控制台窗口的程序,您必须编写WinMain()而不是main(),因此SDL用一个不太好的宏替换了您的main()SDL_main(),然后提供了一个静态库中的WinMain()来调用您的SDL_main(),这样就能正常工作...除非出现问题。 - rodrigo
2
看起来这可能不再是正确的方法(即使曾经是正确的方式),参见此答案 - Herohtar
SDL更喜欢您的主函数采用int main(int argc, char* argv[])的形式。这个答案给出了更详细的解释。 - Vargo

45

另一个选项是使用通常的参数定义自己的main函数。

int main(int argc, char *args[])
{
    // Your code here
}

这样应该可以解决错误。

如果您不使用这些参数,但也想摆脱编译器警告,您可以在主函数中使用这个技巧。

(void)argc;
(void)args;

这是真正的解决方案。我原来有 int main(int argc, const char ** argv),将第二个参数改为 char *argv[] 就解决了问题。甚至在 SDL_main.h 的 main 宏的注释中都写着:“应用程序的 main() 函数必须使用 C 链接调用,并且应该像这样声明:int main(int argc, char *argv[])”。 - daiscog
@megaflop 很有趣,你现在使用的是哪个版本的SDL?我需要再确认一下我过去使用的版本,我想它是1.2。如果你能确认最近的版本是否有所改变,我会编辑我的帖子并添加这个细节!非常感谢 :) - ForceMagic

14

SDL文档中的默认解决方案:

简要概述:

#define SDL_MAIN_HANDLED
#include "SDL.h"

完整示例:

使用此函数绕过未使用SDL_main()作为入口点时,SDL_Init()失败的问题。

#define SDL_MAIN_HANDLED
#include "SDL.h"

int main(int argc, char *argv[])
{
    SDL_SetMainReady();
    SDL_Init(SDL_INIT_VIDEO);

    ...

    SDL_Quit();

    return 0;
}

来源: https://wiki.libsdl.org/SDL_SetMainReady


原本也想评论同样的事情。SDL_main.h 中有关于此的说明。 - CristianDonosoC
1
这解决了我一直遇到的错误,并且似乎是正确的做法,而不是旧的被接受的答案。 - Herohtar

1
罪魁祸首很可能是SDL_main.h文件。请检查您是否包含了该文件,因为其中有一个讨厌的定义。
#define main SDL_main

我没有包括SDL_main,只有SDL和SDL_image,我进行了双重检查。 - OddCore
使用Visual Studio 2012和SDL 1.2.15处理了DosBox源代码。 - eduardomozart

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接