SDL入门之一 SDL装载,退出,错误信息处理

转自:https://blog.csdn.net/lf426/article/details/2086634及后续文章

1.1:SDL是什么? 

        SDL是Simple DirectMedia Layer(简易直控媒体层)的缩写。它是一个跨平台的多媒体库,以用于直接控制底层的多媒体硬件的接口。这些多媒体功能包括了音频、键盘和鼠标(事件)、游戏摇杆等。当然,最为重要的是提供了2D图形帧缓冲(framebuffer)的接口,以及为OpenGL与各种操作系统之间提供了统一的标准接口以实现3D图形。从这些属性我们可以看出,SDL基本上可以认为是为以电脑游戏为核心开发的多媒体库。
        SDL支持主流的操作系统,包括Windows和Linux。在官方的介绍中,我们可以找到它所支持的其他平台。(SDL supports Linux, Windows, Windows CE, BeOS, MacOS, Mac OS X, FreeBSD, NetBSD, OpenBSD, BSD/OS, Solaris, IRIX, and QNX. )。SDL本身从C语言开发,并且能很好的在C++等高级语言中使用。在官方可以看到SDL所支持的语言很多。(Including Ada, C#, Eiffel, Erlang, Euphoria, Guile, Haskell, Java, Lisp, Lua, ML, Objective C, Pascal, Perl, PHP, Pike, Pliant, Python, Ruby, Smalltalk, and Tcl. )
        SDL在GNU LGPL version 2下发布,这意味着你可以免费的使用。并且可以免费的用于商业软件的制作(只要你直接使用SDL的动态链接库,Windows下的SDL.dll)。如果你将SDL库编译进了自己的二进制代码中,你需要指明你所使用的SDL库的版本以及包括你自己修改的源代码,并说明这些代码的原始出处。这是很宽松的法律,你可以用如此强大的多媒体库完全合法的免费开发商业游戏。

 

1.2 下载源码

http://www.libsdl.org/download-2.0.php

 

1.3 SDL的装载,位标(flags)

第一个SDL函数是:int SDL_Init(Uint32 flags);

它的返回值是int,这个我们很熟悉。如果SDL成功初始化装载,函数返回0,如果异常,则返回-1

 

Uint32 是什么?

SDL使用了一个简单的约定:U就是unsigned(无符号,意味着非负)的意思,与之对应的S代表signed(有符号,可正可负);

int还是整数的意思;32表示占32位,类似的,还可以占1至4个字节,即8,16,32,64位。Uint32的意思就是无符号的,占32位的整数类。

 

flags是什么意思?

在计算机里,通常把flag叫做位标——其实,bit flag才是位标,不过这种用法貌似已经是一种习惯。所以,从flags字面,我们至少可以理解到三层含义

1) 关键字“位”,这意味着我们需要用二进制的观点看这个值,并且,这个值可以参与位运算;

2) 关键字“标”,这显然是标记的意思。小狗通常采用一些不文明的手段表明某个区域是自己的势力范围,而人类则通常采用插一面代表自己势力的旗帜,所以这就是flag的本意。

3) 关键字"s",这里使用了复数,表明我们可以不止插一面旗。

函数的位标的定义:(就在SDL.h文件中)

#define    SDL_INIT_TIMER        0x00000001

#define SDL_INIT_AUDIO        0x00000010

#define SDL_INIT_VIDEO        0x00000020

#define SDL_INIT_CDROM        0x00000100

#define SDL_INIT_JOYSTICK    0x00000200

#define SDL_INIT_EVERYTHING    0x0000FFFF

 

SDL_WasInit?

第二个函数 int SDL_WasInit(Uint32 flags);

官方文档里面举了3个例子,后面我将举一个我个人觉得比较直观的程序例子。

/* Get init data on all the subsystems */

Uint32 subsystem_init;

subsystem_init=SDL_WasInit(SDL_INIT_EVERYTHING);

if(subsystem_init&SDL_INIT_VIDEO) 

  printf("Video is initialized./n");

else 

  printf("Video is not initialized./n");

 

 /* Check for two subsystems */

Uint32 subsystem_mask=SDL_INIT_VIDEO|SDL_INIT_AUDIO;

if(SDL_WasInit(subsystem_mask)==subsystem_mask) 

  printf("Video and Audio initialized./n");

else 

  printf("Video and Audio not initialized./n");

 

1.4 第三个函数SDL的退出函数,其原形是:void SDL_Quit(void);

通常,我们在可以预测程序结束的时候直接使用语句:SDL_Quit();
更多的时候,以及SDL官方文档里面,也推荐使用:atexit(SDL_Quit);

一个安全退出SDL的函数如下:

void endSDL(){   

  if ( SDL_WasInit(SDL_INIT_EVERYTHING) == 0 ) {       

     std::cout << "SDL was NOT running!/n";       

    return;   

  }   

  SDL_Quit();   

  std::cout << "SDL_Quit successfully./n";   

   return;

}

 

下面是完整测试程序:

test.h

#include <iostream>
#include "SDL/SDL.h"

void beginSDL();
void endSDL();

 

test.cpp

#include "test.h"

void beginSDL(){   

  if ( SDL_WasInit(SDL_INIT_EVERYTHING) != 0 ) {       

    std::cout << "SDL is already running./n";       

    return;   

  }   

  if ( SDL_Init(SDL_INIT_EVERYTHING) == -1 ) {       

    throw "Unable to init SDL!";   

  }   

  std::cout << "SDL is running successfully./n";   

  return;

}

void endSDL(){   

  if ( SDL_WasInit(SDL_INIT_EVERYTHING) == 0 ) {       

    std::cout << "SDL was NOT running!/n";       

    return;   

  }   

  SDL_Quit();   

  std::cout << "SDL_Quit successfully./n";   

  return;

}

#include "test.h"

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

  try {       

    beginSDL();   

  }   

  catch ( const char* s ) {       

    std::cout << s << std::endl;       

    return -1;   

  }   

  std::cout << SDL_WasInit(SDL_INIT_EVERYTHING) << std::endl;       

  atexit(endSDL);   

  return 0;

}

 

1.5 中途装载与退出

如果我们在程序一开始只启动了video,在运行的某个期间需要启动audio,之后,又需要关掉video只保持audio听声音应该怎么做呢?

先说中途装载。我们首先想到的,还是通过SDL_Init();来装载audio。这看似合理的,而且通过本人试验,发现事实上也是可行的。

但是,我们前面分析过一个逻辑,就是一个程序最好只装载一次Init,这样更容易看出来SDL是从什么时候开始工作的。

那么,为了表明之后的装载是在SDL某些flags已经装载之后的中途装载,SDL提供了一个基本上类似的函数:

int SDL_InitSubSystem(Uint32 flags);

与Init一样,返回值为0则成功装载,-1则失败。       

中途退出某些flags的问题,我们显然就不能用SDL_Quit();了,因为这是所有flags全退。

SDL提供了中途退出某些flags的函数:void SDL_QuitSubSystem(Uint32 flags);

一段演示如何中途装载与中途退出的大致过程:

SDL_Init(SDL_INIT_VIDEO);

SDL_InitSubSystem(SDL_INIT_AUDIO);

 SDL_QuitSubSystem(SDL_INIT_VIDEO);

SDL_Quit();

 

1.6 SDL错误信息

在前面的例子中,我们自己提供了出现异常的错误信息,实际上,SDL也提供了自己的错误信息返回函数:

在官方文档中提供的示范例子是C风格的表述:

if (SDL_Init(SDL_INIT_EVERYTHING) == -1)
{
    printf("SDL_Init Failed: %s/n", SDL_GetError());
    // Unrecoverable error, exit here.
}

值得注意的是,这个函数的返回值是C风格字符串char* ,当我们使用C++风格的异常处理的时候,如果

throw SDL_GetError();

那么,应该catch一个char*对象

catch ( const char* s ) {}

当我们并不是很熟悉SDL内置的错误信息的时候,自己写异常信息是更值得推荐的选择。

最后介绍的函数是 void SDL_ClearError(void);

它将清除所有错误信息。这用于清除掉你已经处理过的错误信息——否则即使没有异常,你仍然可能收到上次异常的错误信息。

 

posted @ 2019-05-06 15:12  HenryLiuY  阅读(721)  评论(0)    收藏  举报