【问题标题】:SDL_QUIT events work with g++ but not gccSDL_QUIT 事件适用于 g++ 但不适用于 gcc
【发布时间】:2015-01-11 06:46:50
【问题描述】:

我想将 SDL 与 C 而不是 C++ 一起使用,但我无法让事件工作。 如果它是一个 .c 或 cpp 文件并使用 g++ 编译,则此代码可以完美运行,如果它是一个 .cpp 文件并使用 gcc 编译,它也可以完美运行。但是,如果它是一个 .c 文件并使用 gcc 编译,它编译得很好,但 SDL_QUIT 事件实际上并没有做任何事情,窗口就会永远挂起。

#include<SDL2/SDL.h>
#include <stdio.h>

//Screen dimension constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 400;


int init();
int loadMedia();
void mainLoop();
void close();

SDL_Window* window =  NULL;
SDL_Surface* screenSurface = NULL;
SDL_Surface* helloWorld = NULL;



int main( int argc, char* args[] ){

  if( !init() ){

printf("Failed to initialize!\n"); 

  }
  else{

if( !loadMedia() ){
    printf("Failed to load media!\n");
}
else{
    mainLoop();

  }
}

  close();

  return 0;

}


void mainLoop(){

  int quit = 0;

  SDL_Event e;

  while( !quit ){

    while( SDL_PollEvent( &e ) != 0 ){
    if(e.type == SDL_QUIT){
        quit = 1;
    }
    }

    SDL_BlitSurface( helloWorld, NULL, screenSurface, NULL);
    SDL_UpdateWindowSurface( window );
  }

}


int init(){

int success = 1;

//initialize sdl
if( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_EVENTS) < 0){

  printf("SDL could not initialize! SDL_Error: %s\n" , SDL_GetError() );
  success = 0;
}
  else {

//create window
window = SDL_CreateWindow( "SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );

    if( window == NULL ){
      printf( "Window could not be created! SDL_Error: %s\n", SDL_GetError() );
      success = 0;
    }
    else {
      screenSurface = SDL_GetWindowSurface( window );
    }
  }

  return success;
}


int loadMedia(){

  int success = 1;

  helloWorld = SDL_LoadBMP("images/helloWorld.bmp");
  if( helloWorld == NULL ){
  printf(" Unable to load image %s! SDL_Error: %s\n", "images/helloWorld.bmp", SDL_GetError() );
  success = 0;
  }
  return success;

}


void close(){

//deallocate surface
SDL_FreeSurface( helloWorld);
helloWorld = NULL;

//Destroy window
SDL_DestroyWindow( window );
window = NULL;

//Quit SDL subsystems
SDL_Quit();
}

【问题讨论】:

  • 有问题的代码没有错。您正在执行哪些操作来产生 QUIT 事件?请为您的问题制作完整的可编译最小示例并将其包含在问题中。
  • 单击窗口上的 X 按钮,什么也不做。此外,如果我添加其他键或鼠标事件,它们在纯 C 中不起作用,但切换到 C++ 编译器或源代码会导致所有 sdl 事件正常工作
  • 如果你坚持不发布完整的例子,那么这个问题是无法回答的。
  • 对不起,我误读了您的问题。用完整的示例代码更新了我的第一篇文章。我也在运行 Ubuntu 14.04

标签: c gcc sdl sdl-2


【解决方案1】:

我觉得你的问题非常有趣,而且肯定不明显。

您的问题是由名称为 close 的函数引起的。这是关闭文件描述符的函数的标准 POSIX 名称。与系统功能冲突。当调用SDL_Init 时,它会连接到X 服务器,查询一些值,然后断开连接(使用XCloseDisplay)。 XCloseDisplay,除其他外,在其套接字描述符上调用 close。问题是,您已经覆盖了系统 close,而是调用了您的系统 - 这样不仅套接字保持未关闭,而且您的代码也调用了 SDL_Quit,这将停止任何进一步的 SDL 调用。

使用 C++ 链接时,函数名称会被修改(修改对于函数重载之类的事情至关重要),因此其结果名称将类似于 _Z5closev,不再与系统函数冲突。事实上,如果在函数声明之前添加extern "C",在 C++ 中也会遇到同样的问题。

解决方法是重命名您的函数(最好不要使用标准名称),或在其声明之前添加 static 说明符,这将限制其仅与当前翻译单元的链接。

链接器不会报告多重定义冲突,因为close 被标记为弱符号(注意它前面的W):

$ nm -D libc-2.19.so | grep close
# <skiped>
000da660 W close

【讨论】:

【解决方案2】:

它与我一起工作如下(这是在 Mac 中)

gcc main.c -o test -I/Library/Frameworks/SDL2.framework/Headers  -framework SDL2 

现在实际代码是

#include "SDL.h"
#include <stdio.h>

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

    SDL_Window *window;                    // Declare a pointer


    // Create an application window with the following settings:
    window = SDL_CreateWindow(
        "An SDL2 window",                  // window title
        SDL_WINDOWPOS_UNDEFINED,           // initial x position
        SDL_WINDOWPOS_UNDEFINED,           // initial y position
        640,                               // width, in pixels
        480,                               // height, in pixels
        SDL_WINDOW_OPENGL                  // flags - see below
    );


    // Check that the window was successfully made
    if (window == NULL) {
        printf("Could not create window: %s\n", SDL_GetError());
        return 1;
    }

    int quit = 0;
    SDL_Event e;

    while( !quit ){

        while( SDL_PollEvent( &e ) != 0 ){
            if(e.type == SDL_QUIT){
                quit = 1;
                printf("Closing the window ...\n");
            }
        }
    }

    SDL_DestroyWindow(window);

    // Clean up
    SDL_Quit();
    return 0;
}

关闭窗口后,终端中会出现以下消息

$ gcc main.c -o test -I/Library/Frameworks/SDL2.framework/Headers  -framework SDL2 
$ ./test
Closing the window ...

【讨论】:

    猜你喜欢
    • 2017-11-13
    • 1970-01-01
    • 2021-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-26
    • 1970-01-01
    相关资源
    最近更新 更多