SDL_QUIT 事件适用于 g++ 但不适用于 gcc
SDL_QUIT events work with g++ but not gcc
我想将 SDL 与 C 而不是 C++ 一起使用,但我无法使事件正常工作。
如果此代码是 .c 或 cpp 文件并使用 g++ 编译,或者如果它是 .cpp 文件并使用 gcc 编译,则此代码可以完美运行。但是,如果它是一个 .c 文件并用 gcc 编译它编译得很好,但是 SDL_QUIT 事件实际上没有做任何事情,window 只是永远挂起。
#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();
}
它和我一起工作如下(这是在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;
}
关闭 window 后,终端中会出现以下消息
$ gcc main.c -o test -I/Library/Frameworks/SDL2.framework/Headers -framework SDL2
$ ./test
Closing the window ...
我发现你的问题非常有趣而且肯定不明显。
你的问题是因为你有名称为 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
我想将 SDL 与 C 而不是 C++ 一起使用,但我无法使事件正常工作。 如果此代码是 .c 或 cpp 文件并使用 g++ 编译,或者如果它是 .cpp 文件并使用 gcc 编译,则此代码可以完美运行。但是,如果它是一个 .c 文件并用 gcc 编译它编译得很好,但是 SDL_QUIT 事件实际上没有做任何事情,window 只是永远挂起。
#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();
}
它和我一起工作如下(这是在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;
}
关闭 window 后,终端中会出现以下消息
$ gcc main.c -o test -I/Library/Frameworks/SDL2.framework/Headers -framework SDL2
$ ./test
Closing the window ...
我发现你的问题非常有趣而且肯定不明显。
你的问题是因为你有名称为 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