未定义对'SDL_main'的引用

12

最近我决定尝试在CodeBlocks 10.05中使用SDL。我从http://www.sdltutorials.com/sdl-tutorial-basics上的教程开始,尽力跟着做。不幸的是,我遇到了以下问题:

..\..\..\..\..\..\SDL\SDL-1.2.15\lib\libSDLmain.a(SDL_win32_main.o):SDL_win32_main.c|| undefined reference to `SDL_main'|

当我尝试编译它时。

我已经在这个网站和其他教程(主要是LazyFoo的教程和CodeBlocks维基上的教程)中搜索了很多问题,但似乎找不到解决方案。

  • 在编译器标签(搜索目录)中添加了C:\SDL\SDL-1.2.15\include
  • 在链接器标签中添加了C:\SDL\SDL-1.2.15\lib
  • 按照顺序链接了库:libmingw32.a、libSDLmain.a、libSDL.dll.a
    • 从CodeBlocks安装目录下的MinGW\lib文件夹中添加了libmingw32.a
  • SDL.dll位于System32文件夹和项目文件夹中

尝试按照CodeBlocks维基上的教程进行操作时,当创建一个新的SDL项目时,提示无法在给定的目录中找到SDL.h。

CApp.cpp

#include "CApp.h"
#include "SDL\SDL.h"

CApp::CApp(){
    Surf_Display=NULL;

    Running=true;
}

int CApp::OnExecute(){
    if (OnInit()==false){
        return -1;
}

SDL_Event Event;

while (Running){
    while (SDL_PollEvent(&Event)){
        OnEvent(&Event);
    }
    OnLoop();
    OnRender();
}

OnCleanup();
return 0;
}

int main(int argc, char* argv[]){
    CApp theApp;

    return theApp.OnExecute();
}

CApp.h

#ifndef CAPP_H_INCLUDED
#define CAPP_H_INCLUDED
#include "SDL\SDL.h"

class CApp{
    private:
        bool Running;
        SDL_Surface* Surf_Display;

    public:
        CApp();
        int OnExecute();

    public:
        bool OnInit();
        void OnEvent(SDL_Event* Event);
        void OnLoop();
        void OnRender();
        void OnCleanup();
};



#endif // CAPP_H_INCLUDED

1
如果我没记错的话,你需要提供“SDL_main”,而不是有一个“main”,你需要有一个“SDL_main”。 - Musa
抱歉,您可能能解释一下您所说的是什么吗? 我在编程方面比较新,不太明白。 这是否与我的SDL设置(链接等)有关,还是代码内部的问题?谢谢! - Prismriver
没关系,我看到这已经在SDL_main.h中完成了。 - Musa
你的链接器设置肯定有些问题。按照你描述的方式,它应该可以工作(至少对我来说确实如此)。 - jrok
@jrok,我肯定在lib文件夹中有上述的.a文件。还有._版本(例如“._libSDLmain.a”以及相应的“libSDLmain.a”)。它是从SDL网站提供的“SDL-devel-1.2.15-mingw32.tar.gz”中提取出来的。我只是按F9键来构建和运行项目。 - Prismriver
显示剩余3条评论
7个回答

41

将这些参数放到main函数中。我之前也遇到了这个问题,几秒钟前我修复了它。

int main(int argv, char** args) { }


谢谢!有人愿意/能够解释一下为什么这个有效吗?(请@我) - Jochem Kuijpers
7
@JochemKuijpers 这个特定的函数签名是必要的,因为SDL更改了默认程序入口点解析。在正常情况下,您可以使用许多标准的main函数签名,例如:int main(), void main(), int main(int, char**)等。编译器将接受所有这些变体。但是,正如我在答案中所描述的那样,SDL拦截了主入口点,并调用您的入口点,期望一个特定的签名,该签名不再受编译器解释。 - Marcin Kaczmarek

17
尝试在所有SDL相关头文件之后使用#undef main更新。这不是一个有效的解决方案! 正如HolyBlackCat指出的那样,这是一个相当粗糙的修复方法。SDL替换main函数以执行一些初始化和/或清理工作,否则将无法完成,然后调用实际用户函数。
拦截通过将用户主函数的名称替换为SDL_main来进行处理,使用了一个简单的宏。
#define main SDL_main
用户的函数将不再是应用程序的入口点,而是使用SDL提供的入口点。建议的#undef方法会不顾后果地禁用拦截,人们可以争辩说它根本不应该起作用。对于那些在这个“修复”之后成功编译和运行SDL应用程序的人来说,这必须只是一个平台相关的巧合。
OP错误的正确解决方法是确保包含main的文件被编译和链接,并且该函数具有正确的签名,就像其他人已经发布的一样。

尝试过后问题仍然存在。 - Prismriver
2
你开玩笑吧...我希望我早一个小时发现这个。在OSX上工作良好。 - nevelis
3
为什么这样修复问题? - zoran404
即使看似工作正常,我们也不应该这么做。SDL有 #define main SDL_main 是因为它需要在执行用户代码之前在 main() 中进行一些初始化操作。如果您抛弃此初始化操作,则可能无法正常工作。 - HolyBlackCat
很抱歉让它持续了这么久。当然,这不是一个正确的解决方案。我早就意识到了,并想写一个更新,但我从来没有时间去全面理解问题以及为什么我的“解决方案”有效。 - Marcin Kaczmarek

7
我能想到的唯一合理的原因是,当您创建包含main的文件时,您可能忘记将其添加到构建目标中。
您应该在我的main.cpp所在的列表中看到CApp.cpp。右键单击它并单击属性。在弹出的窗口中单击“生成”选项卡。您应该看到这个:
点击确定,按Ctrl+F11(重新生成)。
祝你好运。

非常感谢!我简直不敢相信这就是问题所在! - Prismriver
显然,main函数的这个确切语法/签名是必需的。如果你只使用许多编译器支持的 int main() { },它是不起作用的。如果有人知道原因,请告诉我。 - Jochem Kuijpers

2

最近我遇到了这个问题,看了一些YouTube视频并按照LazyFoo的安装指南进行了操作,但一直出现“Undefined reference to SDL_main”错误。

在成功将minGW文件链接到我的项目属性后,我按照这里所说的一切做了,但是直到我在主函数中添加了int main (int argv, char** args)才成功解决了问题。

using namespace std;

int main(int argv, char** args) {    if(SDL_Init(SDL_INIT_VIDEO)<0)    {
       cout<<"Endl Init Failed."<<endl;
       return 1;    }

   cout<<"SDL Init succeeded."<<endl;

   SDL_Quit();    return 0; }

我仍然不清楚它为什么有效,但无论如何都有效了。


那么你到底改了什么?是将 int main() 替换为 int main(int argv, char** args) 吗? - HolyBlackCat
没错,就用那个,希望它能像在我的情况下一样工作。 - NJOKU CHUKWUDI
我们已经有一个建议提供了完全相同的事情,这就是为什么我在问。 - HolyBlackCat
你的方法可行,但对我来说 char const *argv[] 不起作用。什么鬼? - jksevend

1

0

了解到SDL1已经过时,不应该再使用它,但出于某些原因,CodeBlocks仍然会插入一个#include <SDL/SDL.h>,即使您选择创建一个SDL2项目,所以您可能需要将该包含更改为#include <SDL2/SDL.h>


0

这是我搜索时遇到的第一个问题。 没有任何解决方案适用于我。 最终,我找到了适合我的方法。我将我的答案发布在这里,供“任何同行漫游者”参考。

我的问题是我尝试编译一些旧的 C 游戏而不是 C++ 游戏。 对我有帮助的解决方案之一是将 main.c 重命名为 main.cpp, 然后告诉 CMake 对所有 C 文件使用 CPP 编译器。 最终,这是我的 CMakeLists.txt 的一部分:

# set minimum cmake version
cmake_minimum_required(VERSION 3.19 FATAL_ERROR)

# project name and language
project(FootballManager LANGUAGES CXX)

# This is mandatory too, because otherwise they are not compiled an linked.
file(GLOB_RECURSE CFILES "${CMAKE_SOURCE_DIR}/*.c")
SET_SOURCE_FILES_PROPERTIES(${CFILES} PROPERTIES LANGUAGE CXX)

# list sources
list(APPEND _sources config.h)
# ... removed some of the other sources for brevity ...
list(APPEND _sources misc.c)

# Link SDL, yes this is SDL1.2
find_package(SDL REQUIRED)
include_directories(FootballManager ${SDL_INCLUDE_DIRS})

add_executable(fm main.cpp ${_sources})

target_link_libraries(fm ${SDL_LIBRARIES})

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